派生自模板基类的模板构造函数

时间:2014-10-24 18:11:47

标签: c++ templates inheritance c++11

只是好奇,是否有可能继承模板类和派生类的构造函数,调用基类的构造函数,它也是模板化的,并且没有从中推导出类型的参数?

template<typename T>
struct Base {
    template<typename D>
    Base() {                // no argument of type D to infer from
        static_assert(std::is_same<T,D>::value, "");
    }
};

struct Derived : Base<int> {
    Derived()  : Base<int>::Base<int>() {} // is there a way to write it correctly?
};

在我的特定情况下,我可以通过模板方法替换模板构造函数,但仍然是一个关于语言灵活性的有趣问题。

3 个答案:

答案 0 :(得分:4)

C ++标准对此有何看法(第14.8.1节):

  

[注意:因为显式模板参数列表遵循函数模板名称,并且因为在不使用函数名称的情况下调用转换成员函数模板和构造函数成员函数模板,所以无法为这些函数提供显式模板参数列表功能模板。 - 结束说明]

这是一个注释,而不是一个规则,因为它实际上是另外两个规则的结果,一个在同一部分:

  

在引用函数模板特化时,可以通过使用模板参数列表限定函数模板名称来指定模板参数,方法与使用类模板特化时指定的模板参数相同。

和12.1

  

构造函数没有名称。

答案 1 :(得分:3)

构造函数模板的模板参数必须从它们的参数中推导出来,不可能为构造函数显式指定模板参数。

因此,让Base取一个推导出参数的伪参数:

template <typename T>
struct dummy { }; // to prevent instantiation of T

template <typename T>
struct Base
{
    template <typename D>
    Base(dummy<D>)
    {
        static_assert(std::is_same<T, D>::value, "");
    }
};

struct Derived : Base<int>
{
    Derived() : Base<int>(dummy<int>{}) { }
};

答案 2 :(得分:1)

顺便提一下这个问题,看起来似乎是一种荒谬的偏执狂。

想想普通课程:

class Base 
{
public:
    Base() {}
};

class Derived: public Base
{
public:
    Derived() //< default ctor
      :Base  //< this is the Base type
           () //< this selects what ctor to call
    {}
};

请注意,您致电:Base(),其解析为Base::Base(),而不是:Base::Base()

现在,通过逐化Base::Base(),您实际上正在尝试承认Base可以有许多不同的默认ctor(())。这是对“默认”的概念本身的无意义的尊重。

即使Base本身不是模板,也是不可能的:

class Base
{
public:
   template<class T>
   Base() {} //< are there infinite way to default construct Base ?!?
};

Base b; //< so how is b constructed ?

与varadics明显不同的是:

template<class T>
class Base
{
public:
    template<class... S>
    Base(S&&... s) { /* something to do */ }
};

class Derived: public Base<int>
{
public:
   template<class... S>
   Derived(S&&... s) //< Derived varadicly initialized
         :Base //< base type ...
         (std::forward<S>(s)...) //< ... to initialize with what
   {}
};

请注意,如果s为空,您实际上是从Base::Base()拨打Derived()::Derived(),并使用<>(没有参数)

进行语音化