Bug 81198 - [concepts] Same type constraints not enforced for constrained-type-specifiers specified in trailing return types of abbreviated functions
Summary: [concepts] Same type constraints not enforced for constrained-type-specifiers...
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: c++-concepts
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
Keywords: accepts-invalid
Depends on:
Blocks: concepts
  Show dependency treegraph
Reported: 2017-06-24 19:17 UTC by Tom Honermann
Modified: 2020-08-07 16:59 UTC (History)
2 users (show)

See Also:
Known to work:
Known to fail:
Last reconfirmed: 2020-08-07 00:00:00


Note You need to log in before you can comment on or make changes to this bug.
Description Tom Honermann 2017-06-24 19:17:22 UTC
The Concepts TS (N4641) states the following in [dcl.spec.auto] p4 (this section is now in the WP):

"A constrained-type-specifier C1 within the declared return type of an abbreviated function template declaration does not designate a placeholder if its introduced constraint-expression ( is determined to be equivalent, using the rules in for comparing expressions, to the introduced constraint-expression for a constrained-type-specifier C2 in the parameter-declaration-clause of that function declaration. Instead, C1 is replaced by the template parameter invented for C2 (8.3.5)."

Gcc implements this behaviour (with an exception reported in bug 81139) for abbreviated functions that do not specify a trailing return type, but not for those that do:

$ cat t.cpp
template<typename> concept bool C = true;
template<C> class ct {};
ct<C> af1(C) { return ct<int>{}; }
auto af2(C) -> ct<C> { return ct<int>{}; }
auto v1 = af1('c'); // template instantiation fails.
auto v2 = af2('c'); // template instantiation succeeds.

$ g++ --version
g++ (GCC) 7.1.0

$ g++ -c -fconcepts t.cpp
t.cpp: In instantiation of ‘ct<C> af1(auto:1) [with auto:1 = char]’:
t.cpp:5:18:   required from here
t.cpp:3:31: error: could not convert ‘ct<int>{}’ from ‘ct<int>’ to ‘ct<char>’
 ct<C> af1(C) { return ct<int>{}; }

The expected behaviour is that both template instantiations fail.