Consider the following code:
struct A {
constexpr operator int() { return 42; }
};
template
void foo() {}
void bar(A a) {
foo(
I would say that Clang is correct.
Draft for current C++ (n4296) says:
14.3.2 Template non-type arguments [temp.arg.nontype]
A template-argument for a non-type template-parameter shall be a converted constant expression (5.20) of the type of the template-parameter
And 5.20 §4 says (emphasize mine):
5.20 Constant expressions [expr.const]
...
(4) A converted constant expression of type T is an expression, implicitly converted to type T, where the converted expression is a constant expression and the implicit conversion sequence contains only
(4.1) — user-defined conversions, ...
IFAIK in foo();
a is converted to int with a constexpr user-defined conversion and as such is a converted constant expression.
That being said, we are not far from a edge case here, and my advice would be: do not play with such a construct in production code :-)