1

For a generic library I'm trying to define a concept in terms of having a correct implementation of a traits struct. In particular I want to check that the user has provided all required nested types, static member functions and data members. However, I can't find a way to require a nested templated type(-alias).

I have a declaration of the traits struct

template <typename>
struct trait;

and a specialization for chars

template <>
struct trait<char> {
    template <typename>
    using type = int;
};

I now define my concept in terms of this trait

template <typename T>
concept bool SatisfiesTrait = requires() {
    typename trait<T>;                  // require the user to have spcialized 
                                        // for their type

    typename trait<T>::type<long long>; // require the nested template
};

as well as a function requiring a type satisfying this concept

constexpr bool foo(SatisfiesTrait) { return true; }

In my main method I then try to call this function with a char:

int main() {
    foo('c');
}

When compiling all this with GCC I get the error message

prog.cc:15:24: error: 'trait<T>::type' is not a type
     typename trait<T>::type<long long>;
                        ^~~~
prog.cc: In function 'int main()':
prog.cc:26:11: error: cannot call function 'constexpr bool foo(auto:1) [with auto:1 = char]'
    foo('c');
           ^
prog.cc:18:16: note:   constraints not satisfied
 constexpr bool foo(SatisfiesTrait) {
                ^~~
prog.cc:18:16: note: in the expansion of concept 'SatisfiesTrait<auto:1>' template<class T> concept const bool SatisfiesTrait<T> [with T = char]

However, when I change my main function to

int main() {
    typename trait<char>::type<long long> v;
    (void) v;

    foo('c'); 
}

and comment out the requirement of the nested alias template it compiles just fine. The same problem occurs when the nested type has a non-type template parameter instead of a type parameter.

Am I doing something wrong here or is this a bug in GCCs implementation of the Concepts TS?

The code can also be found on Wandbox.

Corristo
  • 4,911
  • 1
  • 20
  • 36
  • `typename trait::template type;` – aschepler Oct 29 '17 at 22:43
  • @aschepler Nope, doesn't work either. I've tried several combinations already. Adding the `template` specifier just changes the error message to `prog.cc:15:37: error: expected template-name before '<' token typename trait::template type;` – Corristo Oct 29 '17 at 22:46
  • Interesting. Reopened. – aschepler Oct 29 '17 at 22:50
  • 1
    I got lost in the grammar trying to make sense of it. In any case as a workaround you can pass your type as a template argument, e.g. to the humble `template using alias = T;`. That would leave you with a `typename alias::template type>;` requirement. – Luc Danton Nov 07 '17 at 12:02

0 Answers0