template<typename T, int V>
class AwesomeClass // [1]
{
public:
AwesomeClass(T baseValue)
: m_value(baseValue + V)
{
}
T get() const
{
return m_value;
}
private:
T m_value;
};
#ifdef USE_ALIAS_TEMPLATES // [2]
template<typename T>
using AwesomeClassWithOne = AwesomeClass<T, 1>;
template<typename T>
using AwesomeClassWithTwo = AwesomeClass<T, 2>;
#else // [4]
template<typename T>
class AwesomeClassWithOne: public AwesomeClass<T, 1>
{
using AwesomeClass<T, 1>::AwesomeClass;
};
template<typename T>
class AwesomeClassWithTwo: public AwesomeClass<T, 2>
{
using AwesomeClass<T, 2>::AwesomeClass;
};
AwesomeClassWithOne(int) -> AwesomeClassWithOne<int>;
AwesomeClassWithTwo(int) -> AwesomeClassWithTwo<int>;
#endif
int main()
{
AwesomeClassWithOne firstObj(20); // [3]
AwesomeClassWithTwo secondObj(20);
return firstObj.get() + secondObj.get();
}
我有一个班级AwesomeClass
[1],它有两个模板参数,typename T
和int V
。 V
是我不希望向该类用户公开的内部详细信息,因此我想提供仅AwesomeClassWithOne
和AwesomeClassWithTwo
之类的别名,例如T
和V
}作为模板参数,并且已将 const {campaignOptions, campaignValue, campaignName} = this.props;
...
<Typeahead
labelKey="label"
allowNew
placeholder="Campaign Name..."
onInputChange={campaignName}
options={campaignOptions}
selected={campaignValue}
/>
绑定到某个值(在我的示例中分别为1和2)。
Alias模板似乎适合这个[2]。但是,从C ++ 17开始,似乎参数推导不能与别名模板一起使用,所以我做不到[3]。
所以我想出了一个替代[4],它涉及为我想要的每个“别名”类型创建新的派生类,继承基类中的所有构造函数,然后创建演绎指南以使自动演绎工作(基类构造函数)似乎没有像普通构造函数那样导致自动演绎指南; related question)。
这看起来像是一个合适的解决方法吗?与别名模板解决方案相比,我可以期待看到任何奇怪的副作用吗?
答案 0 :(得分:1)
遗憾的是,C ++ 17不接受类型别名的演绎指南。
但你可以使用古老的make-something方式(std::make_pair()
,std::make_tuple()
,std::make_unique()
等。)
例如:如果您定义,切换模板参数的顺序,makeAwesome()
函数如下
template <int V, typename T>
AwesomeClass<T, V> makeAwesome (T && t)
{ return { std::forward<T>(t) };
您可以获取AwesomeClass<T, V>
个对象,说明V
并推断T
,将其调用如下
auto firstObj = makeAwesome<1>(20);
如果您不希望向用户公开整数V
部分,则可以添加
template <typename T>
auto makeAwesomeWithOne (T && t)
{ return makeAwesome<1>( std::forward<T>(t) ); }
template <typename T>
auto makeAwesomeWithTwo (T && t)
{ return makeAwesome<2>( std::forward<T>(t) ); }
并且在main()
中你可以写
auto firstObj = makeAwesomeWithOne(20);
auto secondObj = makeAwesomeWithTwo(20);
我知道编写大量几乎等于的makeAwesomeWith-number函数很烦人。
如果使用旧的C风格的函数宏不会吓到你(它们是邪恶的,恕我直言,但在这样的情况......)你可以自动神奇地创建makeAwesomeWith-number函数,如下所示
#define MakeAwesomeWith(Str, Num) \
template <typename T> \
auto makeAwesomeWith ## Str (T && t) \
{ return makeAwesome<Num>( std::forward<T>(t) ); }
MakeAwesomeWith(One, 1);
MakeAwesomeWith(Two, 2);
// ...
以下是完整的工作(基于宏)示例
#include <iostream>
#include <utility>
template <typename T, int V>
class AwesomeClass
{
public:
AwesomeClass (T baseValue) : m_value(baseValue + V)
{ }
T get () const
{ return m_value; }
private:
T m_value;
};
template <int V, typename T>
AwesomeClass<T, V> makeAwesome (T && t)
{ return { std::forward<T>(t) }; }
#define MakeAwesomeWith(Str, Num) \
template <typename T> \
auto makeAwesomeWith ## Str (T && t) \
{ return makeAwesome<Num>( std::forward<T>(t) ); }
MakeAwesomeWith(One, 1);
MakeAwesomeWith(Two, 2);
int main ()
{
auto firstObj = makeAwesomeWithOne(20);
auto secondObj = makeAwesomeWithTwo(20);
std::cout << (firstObj.get() + secondObj.get()) << std::endl;
}
答案 1 :(得分:1)
使用别名模板。
类模板参数推导不适用于别名模板(并且不清楚这可能意味着什么),但是不清楚类模板参数推导是否适用于inherited constructors either。这仍然是一个悬而未决的问题,需要加以解决。
此外,您实际上并不想要引入新类型 。您非常希望AwesomeClass<T, 1>
成为类型。因此,AwesomeClassWithOne<T>
和AwesomeClass<T, 1>
实际上不同会导致问题。这些不是你真正想要的问题,特别是如果你这样做的唯一理由是允许类模板参数推断。
如果真的需要该功能,请提供make_*()
帮助器,就像我们以前习惯写的一样。