Why is a C++ template accepting an array not more specialized than one accepting a pointer according to GCC 5.3 and Clang 4.0?

此生再无相见时 提交于 2019-12-03 12:27:53

问题


Why are the next two template declarations ambiguous (so neither is more specialized than the other)? I know this question has been raised many times on Stack Overflow, but usually, people answer how to resolve ambiguity, not why it's happened.

I. template <class T> void func(char* buf, T size) {}

II. template <std::size_t N> void func(char (&buf)[N], std::size_t size) {}

Trying to pass steps of the C++14 standard to resolve partial function template ordering (14.5.6.2):

To produce the transformed template, for each type, non-type, or template template parameter (including template parameter packs (14.5.3) thereof) synthesize a unique type, value, or class template respectively and substitute it for each occurrence of that parameter in the function type of the template.

Transformed function I template's function type is: void func(char*, U1), where U1 is some unique synthetic type.

Transformed function II template's function type is: void func(char (&buf)[N1], std::size_t), where N1 is some unique synthetic value.

Using the transformed function template’s function type, perform type deduction against the other template as described in 14.8.2.4.

So let's try to perform type deduction on one side (using the first template as an argument and the second one as a parameter template) and on the opposite side.

Case 1.

Parameter template: template <std::size_t N> void func(char (&buf)[N], std::size_t size). Transformed argument template: void func(char*, U1).

Trying to deduce template parameters. "char (&buf)[N]" can't be deduced from "char*" type. U1 doesn't match std::size_t type either. Failed.

Case 2.

Parameter template: template <class T> void func(char* buf, T size). Transformed argument template: void func(char (&buf)[N1], std::size_t).

Trying to deduce template parameters. The first argument of parameter template is not type at all and it's compatible with a char[]. T should be deduced to std::size_t.

So template II should be more specialized and should be selected in the following code:

char buf[16];
func(buf, static_cast<std::size_t>(16));

Why is this not true for GCC 5.3 and for Clang 4.0?


回答1:


The template declarations are not ambiguous; the following code compiles and runs OK:

#include <iostream>
#include <string>

using namespace std;

template<class T>
void func(char* buf, T size) {cout<<"void func(char*,T)\n";}
template<size_t N>
void func(char (&buf)[N], std::size_t size) {
  cout<<"void func(char (&)[],size_t)\n";}

int main() {
  char buf[3];
  func(buf, 2);
  func<3>(buf, 2);
  func(reinterpret_cast<char (&)[3]>(buf), 2);
  //next is ambiguous
  //func(reinterpret_cast<char (&)[3]>(buf), size_t(2));
  func<3>(reinterpret_cast<char (&)[3]>(buf), size_t(2));
  return 0;
}

However, the commented-out call is ambiguous. To disambiguate it use:

func<3>(reinterpret_cast<char (&)[3]>(buf), size_t(2));

This works OK and calls the correct function.



来源:https://stackoverflow.com/questions/48405963/why-is-a-c-template-accepting-an-array-not-more-specialized-than-one-accepting

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