在定义专用模板类构造函数时避免重复

时间:2016-12-24 02:01:43

标签: c++ c++11 templates

假设我有一个模板类:

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只会是Fooint。除此之外,Widget<Foo>Widget<int>以外的任何内容都是无意义的。

上面声明的构造函数适用于Widget<Foo>。有没有办法可以为Widget<int>定义一个专门的构造函数,它以不同的方式分配给t_,但是没有复制粘贴cf_ci_的初始化?

在精神上与Base(a)中对Derived::Derived(int a, int b) : Base(a), b_(b) {}的调用相似吗?

2 个答案:

答案 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_参数构建类成员Widgetstd::string nameWidget有一个带有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) {}