Derive from template constructor of template base class

可紊 提交于 2020-01-10 05:08:05

问题


Just curious, is it ever possible to inherit from a template class and in constructor of the derived class, call constructor of the base class which is also templated and has no arguments to deduce its types from?

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?
};

I can replace template constructor by a template method in my particular case, but still it is an interesting question about the language flexibility.


回答1:


What the C++ standard says about this (section 14.8.1):

[ Note: Because the explicit template argument list follows the function template name, and because conversion member function templates and constructor member function templates are called without using a function name, there is no way to provide an explicit template argument list for these function templates. — end note ]

It's a note, not a rule, because it actually is a consequence of two other rules, one in the same section:

Template arguments can be specified when referring to a function template specialization by qualifying the function template name with the list of template-arguments in the same way as template-arguments are specified in uses of a class template specialization.

and from 12.1

Constructors do not have names.




回答2:


The template arguments of constructor templates must be deduced from their arguments, it's not possible to explicitly specify template arguments for constructors.

As such, have Base take a dummy parameter that deduces the argument:

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>{}) { }
};



回答3:


By the way the question is formulated it looks going towards a nonsensical paranoia.

Just think for plain classes:

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

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

Note that you call :Base(), that resolve into Base::Base(), not :Base::Base()

Now, by templetizing Base::Base() you are in fact trying to admit that there can be many different default ctor (with ()) for Base. That's a nonsense respect ot the concept itself of "default".

Even if Base is not by itself a template, this is not possible:

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

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

Thing gets only apparently different with 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
   {}
};

Note that in case s is empty you are in fact calling Base::Base() from Derived()::Derived(), templetized with <> (no args)



来源:https://stackoverflow.com/questions/26553803/derive-from-template-constructor-of-template-base-class

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!