When CRTP is used inside a template, (or generally when a template parameter is passed as a base class template argument), is it impossible to name the base's member templates in a using
declaration?
template< typename d >
struct base {
template< typename >
struct ct {};
template< typename >
void ft() {}
};
template< typename x >
struct derived : base< derived< x > > {
using derived::base::template ct; // doesn't work
using derived::base::ft; // works but can't be used in a template-id
};
It seems to me that this is a hole in the language, simply because the using-declaration grammar production doesn't incorporate a qualified-id.
using-declaration:
using typename(opt) nested-name-specifier unqualified-id ; // have this
using :: unqualified-id ;
unqualified-id:
identifier
operator-function-id
conversion-function-id
literal-operator-id
~ class-name
~ decltype-specifier
template-id
qualified-id:
nested-name-specifier template(opt) unqualified-id // want this
:: identifier
:: operator-function-id
:: literal-operator-id
:: template-id
If the only rule were using-declaration: using typename(opt) qualified-id
, the only consequences would be
:: conversion-function-id
, :: ~ class-name
, and :: ~ decltype-specifier template-id
which make no semantic sense,:: template-id
which is already expressly forbidden by 7.3.3/5, andtemplate
keyword which already has sufficient specification to patch the hole.Is this analysis correct?
Given that the new grammar were allowed, perhaps a declaration with typename
should import a class template or alias template, and one without typename
should import a function or variable template into the current scope.
using typename derived::base::template ct;
using derived::base::ft;
This might require some additional specification. Also, the current status quo seems to be that dependent template-names always have ambiguous kind (not template-ids), so it's not clear that typename
belongs with ct
at all.
A dependent name is a name that depends on the type or the value of a template parameter. For example: template<class T> class U : A<T> { typename T::B x; void f(A<T>& y) { *y++; } }; The dependent names in this example are the base class A<T> , the type name T::B , and the variable y .
Which is dependant on template parameter? Explanation: Base class is dependant on template parameter.
Class Template Declarationtemplate <class T> class className { private: T var; ... .. ... public: T functionName(T arg); ... .. ... }; In the above declaration, T is the template argument which is a placeholder for the data type used, and class is a keyword.
To instantiate a template class explicitly, follow the template keyword by a declaration (not definition) for the class, with the class identifier followed by the template arguments. template class Array<char>; template class String<19>; When you explicitly instantiate a class, all of its members are also instantiated.
The following works fine with C++11:
#include <iostream>
template< typename d >
struct base {
template< typename >
struct ct {};
template< typename >
void ft() {std::cerr << "cheesecake" << std::endl;}
};
template< typename x >
struct derived : base< derived< x > > {
template<typename X>
using ct = typename derived::base::template ct<X>; // new in C++11
using derived::base::ft;
};
int main()
{
derived<int>::ct<float> c;
derived<int> a;
a.ft<int>();
}
If that is not what you wanted, can you please give an example of how you would want to use ct and ft?
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