How to disambiguate this template?

做~自己de王妃 提交于 2019-12-05 10:19:42
Casey

Array-to-pointer conversion is considered to be an exact match when ranking conversion sequences during overload resolution (C++11 13.3.3.1.1/1 Table 12). Contrary to your intuition, that means that (3) and (5) are equally good matches for A<5> a("0123456789");. The tie is broken - as Xeo says in his comment - in favor of the non-template (3). You may think to trick the compiler by turning (3) into a template as well:

template <typename=void>
A(const char * const) : b{} {}

but doing so will only result in ambiguity of the construction. There's really no easy way to disambiguate const char (&)[] and const char* overloads: the best solution may be to change (3) to accept a pointer and length:

A(const char * const, std::size_t) : b{} {
  std::cout << "size: " << SIZE << " ctor 3\n";
}

Just in passing, I'll note that adding a size_t argument to the const char* const constructor also disambiguates the A("five") case.

EDIT: There is, however, one reasonable way to disambiguate the char* constructor from the array constructor, accept pointer arguments by reference:

template <typename T,
  typename=typename std::enable_if<
    std::is_same<typename std::remove_cv<T>::type, char>{}
  >::type>
A(T* const&) : b{} { std::cout << "size: " << SIZE << " ctor 3\n"; }

[Credit for this particular trick goes to dyp, and possibly Johannes Schaub or Yakk or me (I'm pretty sure it wasn't me).]

This template effectively latches onto the actual type by reference - before array-to-pointer conversion can occur - and then constrains away references to non-pointer types.

  • Why the constructor 3 is preferred over the constructor 5 in the CASE 1?

    Answer: Due to overload resolution. Non templated class functions are first class citizens and as such have higher overload resolution ranking than templated functions. Thus, constructor 3 is preferred over template constructor 5.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!