Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么以下模板函数重载解析不明确?_C++_Template Meta Programming - Fatal编程技术网

C++ 为什么以下模板函数重载解析不明确?

C++ 为什么以下模板函数重载解析不明确?,c++,template-meta-programming,C++,Template Meta Programming,根据我对C++偏序算法的理解,第一个算法似乎是第二个定义的严格子集。因此,无论何时可以选择两者,都应首选第一种。但我收到以下错误消息: p_o.cpp:13:10: error: call to 'f' is ambiguous return f<R>(args...); ^~~~ p_o.cpp:17:12: note: in instantiation of function template specialization 'f<int, double

根据我对C++偏序算法的理解,第一个算法似乎是第二个定义的严格子集。因此,无论何时可以选择两者,都应首选第一种。但我收到以下错误消息:

p_o.cpp:13:10: error: call to 'f' is ambiguous
  return f<R>(args...);
         ^~~~
p_o.cpp:17:12: note: in instantiation of function template specialization 'f<int, double, int>' requested here
  auto a = f<int>(0.3, 1);
           ^
p_o.cpp:7:3: note: candidate function [with T = int, Ts = <>]
T f(T a, Ts ...args) {
  ^
p_o.cpp:12:3: note: candidate function [with R = int, T = int, Ts = <>]
R f(T a, Ts ...args) {
  ^
1 error generated.
p_o.cpp:13:10:错误:对“f”的调用不明确
返回f(args…);
^~~~
p_o.cpp:17:12:注意:在函数模板的实例化中,此处请求专门化“f”
自动a=f(0.3,1);
^
p_o.cpp:7:3:注:候选函数[带T=int,Ts=]
tf(ta,Ts…args){
^
p_o.cpp:12:3:注:候选函数[带R=int,T=int,Ts=]
RF(TA,Ts…args){
^
生成1个错误。
有人能解释一下我哪里出错了吗?我对元编程还不熟悉

#include <tuple>

using namespace std;

template <typename T, typename ...Ts>
T f(T a, Ts ...args) {
  return a;
}

template <typename R, typename T, typename ...Ts>
R f(T a, Ts ...args) {
  return f<R>(args...);
}

int main() {
  auto a = f<int>(0.3, 1);
  static_assert(is_same<int, decltype(a)>::value);
}
#包括
使用名称空间std;
模板
tf(ta,Ts…args){
返回a;
}
模板
RF(TA,Ts…args){
返回f(args…);
}
int main(){
自动a=f(0.3,1);
静态断言(is_same::value);
}

您可以将您的违规案例归结为以下几点:

f<int>(1);
f(1);
这可以解释为对以下内容的调用:

R f<R, T, Ts...>(T, Ts...) // with `R = int`, `T=int` and `Ts = <>`
T f<T, Ts>(T, Ts...) // with `T = int` and `Ts = <>`
rf(T,Ts…)//带'R=int','T=int'和'Ts=`
或致电:

R f<R, T, Ts...>(T, Ts...) // with `R = int`, `T=int` and `Ts = <>`
T f<T, Ts>(T, Ts...) // with `T = int` and `Ts = <>`
tf(T,Ts…)//带'T=int'和'Ts=`
请注意,部分模板排序的更专门的推理适用于参数类型,在这里,它们都是相同的,因此,对于导致歧义的调用,这两个重载被认为同样有效

要解决此问题,您需要一些东西来取消两个重载之一的资格。似乎您希望提取与请求类型匹配的包的第一个成员…为此,您可以使用基于SFINAE的设计:

template< typename R, typename T, typename... Ts >
std::enable_if_t< std::is_same< R, T >::value, R > f( T a, Ts... )
{
    return a;
}

template< typename R, typename T, typename... Ts >
std::enable_if_t< ! std::is_same< R, T >::value, R > f( T, Ts... args )
{
    return f< R >( args... );
}
模板
如果t::值,R>f(ta,Ts…),则启用
{
返回a;
}
模板
std::如果std<!std::是相同的::值,R>f(t,Ts…args)
{
返回f(args…);
}