Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
499 views
in Technique[技术] by (71.8m points)

c++ - clang++ not accepting use of template template parameter when using CRTP

I'm getting compilation errors when trying to call the base class constructor in derived initialization list when using a template template parameter with CRTP.

Problem can be replicated with this snippet of code:

template <template<class> class Derived, class T>
struct base
{
};

template <class T>
struct derived : public base<derived, T>
{
    derived()
        : base<derived, T>()
    { }
};

The offending error messsage:

bug.cpp:10:16: error: template argument for template template parameter must be a class template or type alias template
        : base<derived, T>()
               ^
bug.cpp:10:11: error: expected class member or base class name
        : base<derived, T>()
          ^
bug.cpp:10:11: error: expected '{' or ','
3 errors generated.

This problem only appears to happen on clang (3.4), not g++ (4.8, 4.7, 4.6). I'm compiling with -std=c++11 also.

This is the first time I've needed to use CRTP with template template parameter. Am I doing this okay and it's a problem with clang++ or not?

I've grown to trust clang++ error messages more than g++ of late!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Your code is legal.

From the C++11 Standard, section 14.6.1:

Like normal (non-template) classes, class templates have an injected-class-name (Clause 9). The injected-class-name can be used as a template-name or a type-name. When it is used with a template-argument-list, as a template-argument for a template template-parameter, or as the final identi?er in the elaborated-type- speci?er of a friend class template declaration, it refers to the class template itself.

Looks like your version of clang is still implementing the old rule. Based on your additional comments, it might be doing so only in the ctor-initializer-list.


User David Rodríguez - dribeas provided a workaround for compilers that haven't fully implemented the C++11 injected-class-name rule. Use any name of the class that isn't unqualified, for example:

derived()
    : base< ::derived, T >()
//          ^^ qualified with global namespace
{ }

Some compilers may require this in the inheritance list also:

template <class T>
struct derived : public base< ::derived, T >
//                            ^^

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...