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 { };
Demo
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).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With