[英]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 並仍然為其提供不同類型的輸入(如float
和double
),但我希望其類型為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.