Home > Mobile >  unexpected behavior with template function overloading
unexpected behavior with template function overloading

Time:11-30

So i have the following snippet which compiles correctly:

template<typename _Tp, typename _Up = _Tp&&>
  _Up
  __declval(long);

//template<typename _Tp>
//  _Tp
//  __declval(char);

template<typename _Tp>
auto declval() noexcept -> decltype(__declval<_Tp>(0));

int main()
{
    declval<int>;
    return 0;
}

and i have this one, which for some reason it doesn't:

template<typename _Tp, typename _Up = _Tp&&>
  _Up
  __declval(long);

template<typename _Tp>
  _Tp
  __declval(char);
  //but if we change char to int it works

template<typename _Tp>
auto declval() noexcept -> decltype(__declval<_Tp>(0));

int main()
{
    declval<int>;
    return 0;
}

The error i get with the second snippet according to clang:

:26:5: error: reference to overloaded function could not be resolved; did you mean to call it?

But when i replace the __declval(char) with __declval(int) the error disappears. I've been scratching my head for some time now, any clues about the underlying cause of this issue?

CodePudding user response:

You are running into effectively the same problem as the following, simpler and equally broken, program:

void foo(long) {}
void foo(char) {}

int main() {
    foo(0);
}

The error is a lot clearer here though:

:5:5: error: call to 'foo' is ambiguous

The issue is that 0, being an int, is equally valid as a char as it is as a long. In both cases, an implicit conversion is required. Since neither is preferable to the other, the call is ambiguous.

There are 3 ways to fix this:

  1. Make sure there is only one overload that is implicitly callable from an int. That's how the original snippet works.

  2. Provide an overload that does not need an implicit conversion for the parameter used at the callsite. This is what using __declval(int) does.

  3. Use a long literal instead of an int one at the callsite. So that __declval(long) is called without the need for an implicit conversion.

auto declval() noexcept -> decltype(__declval<_Tp>(0L));
  •  Tags:  
  • c
  • Related