假设我有一个模板类:
template<typename T>
class Widget {
public:
Widget(const std::string& name, int i) : t_(name), cf_(name), ci_(i) {}
private:
T t_;
const Foo cf_;
const int ci_;
}
并且假设在这种情况下,T
只会是Foo
或int
。除此之外,Widget<Foo>
和Widget<int>
以外的任何内容都是无意义的。
上面声明的构造函数适用于Widget<Foo>
。有没有办法可以为Widget<int>
定义一个专门的构造函数,它以不同的方式分配给t_
,但是没有复制粘贴cf_
和ci_
的初始化?
在精神上与Base(a)
中对Derived::Derived(int a, int b) : Base(a), b_(b) {}
的调用相似吗?
答案 0 :(得分:5)
标签调度和转发构造函数可能有帮助
template <typename> struct Tag {};
template<typename T>
class Widget {
public:
Widget(const std::string& name, int i) : Widget(Tag<T>{}, name, i) {}
private:
Widget(Tag<int>, const std::string& name, int i) :
Widget(Tag<void>{}, 42, name, i)
{}
Widget(Tag<Foo>, const std::string& name, int i) :
Widget(Tag<void>{}, name, name, i)
{}
template <typename U>
Widget(Tag<void>, U&& u, const std::string& name, int i) :
t_(std::forward<U>(u)),
cf_(name),
ci_(i)
{}
private:
T t_;
const Foo cf_;
const int ci_;
};
答案 1 :(得分:1)
专门研究整个Widget<int>
类是一种选择。除此之外,有各种方法可以用来避免专门化整个班级;但是,它们在很大程度上取决于你需要如何构建它。
对于此示例,让我们说Widget<Foo>
您希望使用t_
参数构建类成员Widget
,std::string name
(Widget
有一个带有std::string
参数的构造函数),而对于Widget<int>
,你想要构建一个类成员t_
,它现在将成为int
使用者int i
参数。
首先,定义一个专门的帮助器模板函数,它选择正确的参数:
template<typename T>
auto t_param(const std::string &name, int i);
template<>
auto t_param<Foo>(const std::string &name, int i)
{
return name;
}
template<>
auto t_param<int>(const std::string &name, int i)
{
return i;
}
有了这个,你的构造函数变得简单:
Widget(const std::string& name, int i)
: t_(t_param<T>(name, i)), cf_(name), ci_(i) {}