问题
I was porting some code from MSVC(without permissive-) to linux and I learned that if you call constructor of a template base class in initializer list of your class you must specify all the template parameters or you get an error. Seems kind of redundant, since if you make a mistake in retyping the template parameters it is a hard error:
error: type 'Base<int, true>' is not a direct or virtual base of 'Derived'
full code here:
template <typename T, bool has_x>
struct Base
{
Base(T t): t_(t){
}
T t_=0;
};
template <typename T>
class Derived : public Base<T, false>
{
public:
// : Base<T, true> is hard error
Derived(const T& t) : Base<T, false>(t) {}
};
int main()
{
Derived d(47);
}
Is there a strong reason for this, or just standardization process never took time to special case this use case?
回答1:
You only need to do that when Derived is a template and the type of the base depends on its template parameters.
This compiles, for example:
template <typename T>
class Derived : public Base<int, false>
{
public:
Derived(const T& t) : Base(t) {}
};
As far as I know, here (in member initializer list) Base is actually the injected-class-name of Base<...>, inherited from it like everything else.
And if the type of the base does depend on the template parameters, its inherited injected-class-name becomes inaccessible (at least directly), just like any other member inherited from it.
For a member variable/function, you'd add this-> to access it, but for a type member you need Derived:::
template <typename T>
class Derived : public Base<T, false>
{
public:
Derived(const T& t) : Derived::Base(t) {}
};
来源:https://stackoverflow.com/questions/62556571/why-does-c-require-me-to-repeat-template-arguments-of-my-base-class-in-initali