Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

templated conversion operator type deduction differs in clang and gcc

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:

  • Which is correct? That is, which conforms to the C++ standard?
  • What is causing this difference?
  • In general, what are the type deduction rules being applied to 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.

like image 628
Daisy Sophia Hollman Avatar asked Dec 06 '25 07:12

Daisy Sophia Hollman


1 Answers

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).

like image 134
Barry Avatar answered Dec 09 '25 00:12

Barry



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!