I've been fighting differences between compilers with respect to templated conversion operator type deduction for the past few days, and I've finally boiled down at least one of the differences to a stack-overflow-sized example:
void foo(int i);
struct any_const_reference {
template <typename T>
operator const T&();
};
template <typename T, typename Enable=void>
struct detect_call : std::false_type { };
template <typename T>
struct detect_call<T,
decltype( declval<T>()( any_const_reference() ) )
> : std::true_type { };
The expression detect_call<decltype(foo)>::value
give true
in clang and false
in gcc (using any modern version of either compiler that I can get my hands on, the latest being gcc 5.2 and clang 3.8). Questions:
T
in the conversion operator (or in any conversion operator of this form, e.g., template <typename T> operator T();
), and where are they given in the C++ standard? Note: this seems to be similar to this question: Template argument type deduction by conversion operator (indeed, I've run into that exact difference as well), but I don't quite see the mapping between that answer and this case. If this is just another instance of this issue, then this question boils down to how to map that issue into this use case.
This can be simplified to just actually calling foo()
:
void foo(int ) { }
struct any_const_reference {
template <typename T>
operator const T&();
};
int main() {
foo(any_const_reference{}); // ok on clang
// error on gcc
}
This is a gcc bug (#63217 per TC's comment above). Per [temp.deduct.conv], this should deduce T
as int
since both the reference and qualifiers should be removed (in this case P
is const T&
and A
is int
).