簡體   English   中英

如何僅通過其中一種類型引用具有多種模板類型的 class?

[英]How do I refer to a class with multiple template types by only one of the types?

假設我有一個帶有聲明的 class Shape

template <typename T, typename U, typename V>
class Shape {
   T value;
   U input;
   V input2;

   ...
}

事實上,如果我創建一個Shape object,它的類型將類似於Shape<int, float, double> - 例如。

但是,如果我希望能夠創建一個Shape object 並仍然為其提供不同類型的輸入(如floatdouble ),但我希望其類型為Shape<int>怎么辦?

也就是說,在創建Shape object 之后,我希望調用者只關心其值的類型,而不關心其輸入的類型。 你怎么建議我go一下呢?

我了解到,如果不在頂部聲明模板類型,我就無法存儲模板成員變量。 我也嘗試過使用別名,例如:

template <typename T, typename U, typename V>
using ShapeAlias<T> = Shape<T, U, V>

但這也不管用。 你對我如何能 go 有什么建議嗎?

我正在考慮某種形式的 inheritance,其中有一個只有一種類型的基 class,而派生的 class 包含所有三種類型,但我想我應該在這里檢查。

編輯:我需要第二種和第三種類型,因為用戶可以將 function 傳遞給Shape構造函數來計算 T 的值,它可能如下所示:

auto creator = [](U a, V b){
   return (something of type T)
}

我想將輸入類型的值保留在Shape class 中。

所以從客戶的角度來看,他們的代碼應該是這樣的:

Shape<T> shapeA(Shape<T>(uValue, vValue, creator)

就像現在一樣,他們必須這樣做:

Shape<T, U, V> shapeA(Shape<T, U, V>(uValue, vValue, creator))

看起來您正在尋找 CTAD(類模板參數推導)。 它僅在調用者未指定任何模板參數時有效,因此必須添加一個間接層:

template <typename T>
struct ShapeWrap {
    template <typename U,typename V>
    struct Shape {
        T value;
        U input;
        V input2;
        Shape(const U& u,const V& v) : input(u),input2(v) {}
    };
};

調用者現在可以調用:

auto s = ShapeWrap<int>::Shape(1.0,0.1f);

實例化ShapeWrap<int>::Shape<double,float>


或者通過 function 模板的模板參數推導:

template <typename T, typename U,typename V>
struct Shape {
    T value;
    U input;
    V input2;
    Shape(const U& u,const V& v) : input(u),input2(v) {}
};

template <typename T,typename U,typename V>
Shape<T,U,V> make_shape(const U& u, const V& v) {
    return {u,v};
}



int main() {
    auto s = make_shape<int>(1.0,0.1f);
}

如果創建者 object 僅在構造函數本身中使用,但您不需要存儲值供以后使用,則可以求助於模板化構造函數。 如果您確實需要存儲值,則需要指定包括所有類型參數在內的完整類型,如果用戶必須自己命名類型。 您可以設計 class 使auto可用。

備選方案 1:創建 function 以創建 object。

這允許用戶從左側開始指定一些模板參數,但編譯器會推導出 rest。

template<class Product, class CreatorType, class ...Args>
class Factory
{
public:
    Factory(CreatorType const& creator, Args...args)
        : m_creator(creator), m_arguments(args...)
    {
    }

    Product Create()
    {
        return std::apply(m_creator, m_arguments);
    }
private:
    CreatorType m_creator;
    std::tuple<Args...> m_arguments;
};

template<class Product, class CreatorType, class ...Args>
auto CreateFactory(CreatorType const& creator, Args ... args)
{
    return Factory<Product, CreatorType, Args...>(creator, args...);
}

int main() {

    auto creator = [](int value) -> int { return value + 1; };

    auto factory = CreateFactory<long>(creator, 41); // we're able do add a type conversion int -> long here

    std::cout << "The answer is " << factory.Create() << '\n';
}

備選方案 2:添加 class 模板參數推導 (CTAD) 指南

如果您同意根據調用創建者的結果自動推導返回類型,則可以創建一個自動推導類型參數的 CTAD 指南,前提是用戶未指定任何模板參數。

template<class Product, class CreatorType, class ...Args>
class Factory
{
public:

    Factory(CreatorType const& creator, Args const&...args)
        : m_creator(creator), m_arguments(args...)
    {
    }

    Product Create()
    {
        return std::apply(m_creator, m_arguments);
    }
private:
    CreatorType m_creator;
    std::tuple<Args...> m_arguments;
};

// deduction guideline: the result of calling creator with the arguments is used as the first template parameter
template<class CreatorType, class ... Args>
Factory(CreatorType const&, Args const&...) -> Factory<decltype(std::apply(std::declval<CreatorType>(), std::declval<std::tuple<Args...>>())), CreatorType, Args...>;

int main() {
    auto creator = [](int value) -> int { return value + 1; };

    Factory factory(creator, 41); // type of factory automatically chosen to be Factory<int, ..., int>

    std::cout << "The answer is " << factory.Create() << '\n';
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM