admin管理员组文章数量:1221846
I made a macro for the "implies" operator. It works fine in general, but breaks on Clang when used in a concept or a requires-clause.
run on gcc.godbolt
namespace detail
{
template <typename T>
concept BoolLike = requires(T &&t) {(T &&)t ? true : false;};
struct Implies
{
template <BoolLike T>
friend constexpr bool operator||(T &&lhs, Implies)
{
return !bool((T &&)lhs);
}
};
}
#define IMPLIES ||::detail::Implies{}||
template <typename T>
concept A = true IMPLIES true;
static_assert(A<int>);
Clang says:
<source>:19:18: error: atomic constraint must be of type 'bool' (found '::detail::Implies')
19 | concept A = true IMPLIES true;
| ^~~~~~~
<source>:16:19: note: expanded from macro 'IMPLIES'
16 | #define IMPLIES ||::detail::Implies{}||
| ^~~~~~~~~~~~~~~~~~~
While GCC and MSVC happily accept this code. Which compiler is correct?
I made a macro for the "implies" operator. It works fine in general, but breaks on Clang when used in a concept or a requires-clause.
run on gcc.godbolt.org
namespace detail
{
template <typename T>
concept BoolLike = requires(T &&t) {(T &&)t ? true : false;};
struct Implies
{
template <BoolLike T>
friend constexpr bool operator||(T &&lhs, Implies)
{
return !bool((T &&)lhs);
}
};
}
#define IMPLIES ||::detail::Implies{}||
template <typename T>
concept A = true IMPLIES true;
static_assert(A<int>);
Clang says:
<source>:19:18: error: atomic constraint must be of type 'bool' (found '::detail::Implies')
19 | concept A = true IMPLIES true;
| ^~~~~~~
<source>:16:19: note: expanded from macro 'IMPLIES'
16 | #define IMPLIES ||::detail::Implies{}||
| ^~~~~~~~~~~~~~~~~~~
While GCC and MSVC happily accept this code. Which compiler is correct?
Share Improve this question asked Feb 6 at 19:22 HolyBlackCatHolyBlackCat 96.3k13 gold badges167 silver badges268 bronze badges 2 |1 Answer
Reset to default 6Overloaded logical operators don't really work in constraint expressions (at the top level): the constraint normalization machinery turns expressions of the forms E1 || E2
and E1 && E2
into disjunctions and conjunctions, respectively, based purely on their syntactic form, without regard to whether there is a user-provided overload for the operator ([temp.constr.normal]).
In this particular example, this means that the normal form of A
's constraint-expression contains, among others, an atomic constraint formed from the expression ::detail::Implies{}
, which is never of type bool
.
[temp.constr.atomic]/3:
To determine if an atomic constraint is satisfied, the parameter mapping and template arguments are first substituted into its expression. [...]
E
shall be a constant expression of typebool
.
Since this program never checks the invalid atomic constraint for satisfaction (because ||
short-circuits), it is ill-formed with no diagnostic required ([temp.res.general]/6.4):
The program is ill-formed, no diagnostic required, if
- any constraint-expression in the program, introduced or otherwise, has (in its normal form) an atomic constraint A where no satisfaction check of A could be well-formed and no satisfaction check of A is performed
本文标签: cOverloaded ampamp operators in concepts and requiresclausesStack Overflow
版权声明:本文标题:c++ - Overloaded `&&``||` operators in concepts and requires-clauses - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1739366698a2160072.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
concept A = static_cast<bool>(true IMPLIES true);
works though Demo – Jarod42 Commented Feb 7 at 8:45!a || b
. – HolyBlackCat Commented Feb 7 at 9:25