函数模板重载分辨率混乱

时间:2016-07-11 03:27:17

标签: c++ templates c++11 c++14 c++17

我想知道如何解决对std::make_optional这两个重载的调用:

template< class T >
constexpr std::optional<std::decay_t<T>> make_optional( T&& value );

template< class T, class... Args >
constexpr std::optional<T> make_optional( Args&&... args );

我知道没有make_optional(123)这样的显式模板参数的调用会调用第一个,但是make_optional<int>(123)怎么样?将选择哪个重载,以及通过什么规则?

UPDATE:如果我写了make_optional<string>("hello world"),我将调用第二个重载(即使字符串文字可以隐式转换为string),正确?

1 个答案:

答案 0 :(得分:2)

重载分辨率从确定可行候选者开始,选择具有最佳转换序列的候选者,然后浏览tiebreakers列表。

make_optional(123)只有一个可行的候选者,因为T是第二次重载中未推断的上下文。因此,它是最有可行的候选人。

make_optional<int>(123)为我们提供了两个可行的候选人:

  • make_optional(int&& )[T=int]
  • make_optional<int>(int&& )[T=int, Args={int}]

该函数采用相同的参数(int&&),因此它们在相同的转换序列中同样可行。第一个重载是一个比第二个重载更专业的函数模板(因为它需要一个参数而不是一个可变参数包),所以它是首选的。

make_optional<string>("hello world")为我们提供了两个可行的候选人:

  • make_optional(string&& )[T=string]
  • make_optional<string>(const char(&)[12] )[T=string, Args={const char (&)[12]}]

这里,两个函数不采用相同的参数 - 第一个采用string&&(需要用户定义的字符串文字转换),第二个采用const char(&)[12](这是完全匹配)。因此,第二个重载具有更好的转换顺序,是首选。