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?
Why we use :: template-template parameter? Explanation: It is used to adapt a policy into binary ones.
Templates in c++ is defined as a blueprint or formula for creating a generic class or a function. To simply put, you can create a single function or single class to work with different data types using templates. C++ template is also known as generic functions or classes which is a very powerful feature in C++.
Templates are the mechanism by which C++ implements the generic concept. Simply, they allow you to pass data type as a parameter so that you don't need to write the same code for different data types.
Definition. As per the standard definition, a template class in C++ is a class that allows the programmer to operate with generic data types. This allows the class to be used on many different data types as per the requirements without the need of being re-written for each type.
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) {}
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With