Using declaration for type-dependent template name

c++, crtp, grammar, templates

Solution

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?

Problem

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 - ruling out `:: conversion-function-id`, `:: ~ class-name`, and `:: ~ decltype-specifier template-id` which make no semantic sense, - allowing `:: template-id` which is already expressly forbidden by 7.3.3/5, and - allowing the `template` 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.

Original source