假設我有一個Shape帶有宣告的類:
template <typename T, typename U, typename V>
class Shape {
T value;
U input;
V input2;
...
}
事實上,如果我創建一個Shape物件,它的型別將類似于Shape<int, float, double>- 例如。
但是,如果我希望能夠創建一個Shape物件并仍然為其提供不同型別的輸入(如float和double),但我希望它的型別為Shape<int>.
也就是說,在創建Shape物件之后,我希望呼叫者只關心其值的型別,而不是其輸入的型別。你建議我怎么做?
我了解到,如果沒有在頂部宣告模板型別,我就無法存盤模板成員變數。我也嘗試過使用類似的別名:
template <typename T, typename U, typename V>
using ShapeAlias<T> = Shape<T, U, V>
但這也行不通。你對我該如何解決這個問題有什么建議嗎?
我正在考慮某種形式的繼承,其中有一個只有一種型別的基類,而派生類包含所有三種型別,但我想我應該在這里檢查一下。
編輯:我需要第二種和第三種型別,因為這個想法是用戶將能夠將函式傳遞給Shape建構式以計算 T 的值,它可能如下所示:
auto creator = [](U a, V b){
return (something of type T)
}
我想保留Shape類中輸入型別的值。
所以從客戶的角度來看,他們的代碼應該是這樣的:
Shape<T> shapeA(Shape<T>(uValue, vValue, creator)
就像現在一樣,他們必須這樣做:
Shape<T, U, V> shapeA(Shape<T, U, V>(uValue, vValue, creator))
uj5u.com熱心網友回復:
您似乎正在尋找 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>.
或者通過函式模板的模板引數推導:
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);
}
uj5u.com熱心網友回復:
如果創建者物件僅用于建構式本身,但您不需要存盤值以供以后使用,則可以使用模板化建構式。如果您確實需要存盤值,則需要指定包括所有型別引數的完整型別,如果用戶必須自己命名型別。auto您可以以一種可用的方式設計該類。
備選方案 1:創建一個用于創建物件的函式。
這允許用戶從左邊開始指定一些模板引數,但其余的由編譯器推導。
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:添加類模板引數推導 (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';
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/455267.html
