AnotherRegister
AnotherRegister

Reputation: 31

Is this a BUG about the <concept> lib in c++?

I've met an "internal compiler error" while learning the concept lib in c++...

Environment:

compile cmd: g++ -std=c++17 test.cpp -fconcepts -g -v| more;

some of the compile output:

Thread model: posix
gcc version 8.1.0 (x86_64-posix-seh-rev0, Built by MinGW-W64 project)
COLLECT_GCC_OPTIONS='-std=c++17' '-fconcepts' '-g' '-v' '-save-temps' '- 
shared-libgcc' '-mtune=core2' '-march=nocona'

my codes:

template<class A, class B>
concept bool Test = true;

template<class T>
concept bool Ohh = requires(T t, Test<typename T::type> sth){
    { t.func(sth) };
};

//this one works well !!
// template<class T>
// concept bool OK = requires(T t){
//  { t.func(Test<typename T::type>) };
// };

template<class T>
struct A{
    typedef T type;

    void func(T){}
};

Ohh{T} /* OK{T} works fine */
struct B{
    static const bool value = true;
};

int main(int argc, char *argv[] /*, char *envp[]*/)
{
    cout << B<A<int>>::value;
}

Here are the error msgs:

internal compiler error: in synthesize_implicit_template_parm, at cp/parser.c:39068
 concept bool Ohh = requires(T t, Test<typename T::type> sth){
                                                       ^
libbacktrace could not find executable to open.
...

Is that a bug or I just shouldn't use Test<typename T::type> in requires-expression's parameter list?

Note: I cannot report this bug because account creation is restricted on buggzilla.

Upvotes: 3

Views: 221

Answers (1)

Nicol Bolas
Nicol Bolas

Reputation: 473407

Any internal compiler error is a de-facto compiler bug. The question is, should your code be valid if the compiler were working correctly?

No.

Test<typename T::type> is a constexpr boolean variable, which ultimately boils down to the value true. And a variable is not a legal typename inside of the parameters of a requires expression.

What you want in the parameter is just typename T::type, since that's the type you want to give sth. But what you also want is to restrict this concept to a T which has a ::type typename member.

Basically, you don't need Test:

template<class T>
    requires requires { T::type; }
concept bool Ohh = requires(T t, typename T::type sth){
    { t.func(sth) };
};

Or, if you want to conceptualize the idea of a type which has a ::type typename:

template<class T>
concept bool HasType = requires { T::type; };

template<HasType T>
concept bool Ohh = requires(T t, typename T::type sth){
    { t.func(sth) };
};

I think you're falling into the trap of pre-concepts thinking, where you've tried to use the usual template metaprogramming solution instead of the concept one. Express the requirement you want as directly as possible.

Upvotes: 2

Related Questions