为什么重载(使用enable_if)和通用参考不起作用? 使用MS Visual C++ 2012版本110.51 10601更新1:

为什么重载(使用enable_if)和通用参考不起作用? 使用MS Visual C++ 2012版本110.51 10601更新1:,c++,c++11,overloading,template-meta-programming,C++,C++11,Overloading,Template Meta Programming,呼叫代码: int res = MySh(x); // compiles and returns 3 res = MySh1(x); // doesn't compile with error: error C2893: Failed to specialize function template 'std::enable_if<std::is_same<Fun,int(void)>::value,int>::type MySh1(Fun &&

呼叫代码:

   int res = MySh(x); // compiles and returns 3
   res = MySh1(x); // doesn't compile with error: error C2893: Failed to specialize function template 'std::enable_if<std::is_same<Fun,int(void)>::value,int>::type MySh1(Fun &&)
   res = MySh2(x); // compiles and returns 3

我还没有尝试过其他编译器,但目的是让它与Visual C++ 2012一起工作和/或向微软报告编译器错误。 我想确保我没有忽视一些琐碎的事情,没有犯愚蠢的错误。 当然,样本只是一个摘录,真正的预期用例更复杂,并且与:

编辑: 此外,我还被其他考虑因素弄糊涂了,例如:

   std::is_same<decltype(x), int()>::value; // true
   std::is_same<decltype(x), int(&)()>::value; //false
以及:


显然,我没有注意参数类型和参数Fun类型之间的区别,而不是f和x

答案在错误中,将您的声明替换为

template <typename Fun>
typename std::enable_if<std::is_same<Fun, int(&)()>::value, int>::type 
    MySh1(Fun&& f)
{ 
    return f();
}
发生这种情况的原因是,对于模板空洞的情况,有特殊的处理标准&

如果将一些参数传递给foo,则以下int的保持为例:

传递左值int-T为int& 传递左值常量int-T是常量int& 传递右值int-T为int pass rvalue const int-T是const int
斯科特·梅耶斯的好消息可能会更清楚地说明这一点。

答案在于错误,请将您的声明替换为

template <typename Fun>
typename std::enable_if<std::is_same<Fun, int(&)()>::value, int>::type 
    MySh1(Fun&& f)
{ 
    return f();
}
发生这种情况的原因是,对于模板空洞的情况,有特殊的处理标准&

如果将一些参数传递给foo,则以下int的保持为例:

传递左值int-T为int& 传递左值常量int-T是常量int& 传递右值int-T为int pass rvalue const int-T是const int 斯科特·梅耶斯的好作品可能会更能说明这一点。

在这种情况下,乐趣是一种乐趣&或者一种乐趣常数&或者一种乐趣-&-&&将乐趣绑定到上述三个参考文献中的任何一个,或者可能是乐趣常数-&?不确定指类型推断上下文中的魔法引用

您将其与int进行比较,而不是将其与int的引用、const引用或rvalue引用进行比较

如果你不在乎什么样的简历和参考类型是附加在Fun上的,我建议你使用std::decay

这使得[]->int lambdas有资格成为可用的乐趣。但为什么要到此为止

template <typename Fun>
typename std::enable_if<std::is_convertible<decltype(std::declval<Fun>()()), int>::value>::type 
它们是等价的,并且表示MySh_Alpha返回的类型与传入的f相同。

在该上下文中的Fun是Fun&或Fun常量&或Fun&&&将&&使Fun绑定到上述3个引用中的任何一个,可能还有Fun常量&?不确定指类型推断上下文中的魔法引用

您将其与int进行比较,而不是将其与int的引用、const引用或rvalue引用进行比较

如果你不在乎什么样的简历和参考类型是附加在Fun上的,我建议你使用std::decay

这使得[]->int lambdas有资格成为可用的乐趣。但为什么要到此为止

template <typename Fun>
typename std::enable_if<std::is_convertible<decltype(std::declval<Fun>()()), int>::value>::type 

它们是等价的,并且说MySh_Alpha返回的类型与传入的f相同。

但是如果:std::is_same::value返回true,那么它的理由是什么呢?当然,如果在这个上下文中也应该选择一个有效的int返回类型,那么就启用?理由很简单:当与模板funT一起使用时,universal references规则lvalue变成T&并且您的x函数是lvalue。我理解引用折叠规则,或者我在应用于“simple”类型时是这样想的,但我发现当类型是自由函数。你能详细说明一下对int和signature的需求吗?这是完全一样的。你有你的函数x,你可以把它算作int,就实体而言,它们没有什么不同。因为您声明了您的x函数,所以每当x参与到其他函数参数中时,它就是左值,因此应用左值规则。尝试通过&x,如果将enable_中的签名更改为std::is_,则必须更改签名。希望这是清楚的,或多或少让我思考一下。我还有另一个例子,从int到int的更改并不能解决问题,但是,在这种情况下,我使用的是发布在SO上的第三方实用程序函数,而不是std::is_same::value返回true,那么它的理由是什么呢?当然,如果在这个上下文中也应该选择一个有效的int返回类型,那么就启用?理由很简单:当与模板funT一起使用时,universal references规则lvalue变成T&并且您的x函数是lvalue。我理解引用折叠规则,或者我在应用于“simple”类型时是这样想的,但我发现当类型是自由函数。你能详细说明一下对int和signature的需求吗?这是完全一样的。你有你的函数x,你可以把它算作int,就实体而言,它们没有什么不同。因为您声明了您的x函数,所以每当x参与到其他函数参数中时,它就是左值,因此应用左值规则。尝试通过&x,如果将enable_中的签名更改为std::is_,则必须更改签名。希望这是清楚的,多多少少告诉我
想一想。我有另一个例子,从int到int的更改并不能解决问题,但是,在这种情况下,我使用的是发布在SO上的第三方实用程序函数,而不是std::is_same,在类似问题的背景下。你们两个都有很好的答案,目标相同,所以我很难决定接受哪个答案。相反,我将尝试进行更多测试,完善问题,看看是否有任何真正的编译器问题隐藏在这里。顺便说一句:模板typename std::enable_if::type//typename std::enable_if::type yakfun&&f{return f;}对于自由函数和lambda很好,而不是std::function,注释掉的带有decltype的行在我的Visual C++版本中不编译。第一个版本适用于自由函数和无状态lambda。你错过的那一秒是12月后的第二秒。除非我打错了,否则它应该可以与std::function配合使用。是的,需要偶尔清洁一下眼镜。IMO中有一个输入错误,应该是:typename std::enable_if::type,但即使这样也不行。编译器立即拒绝左侧为false,打印:错误C2039:“type”:不是带[\u Test=false,\u Ty=int]的“std::enable\u if”的成员,您正在使用哪个编译器?我对你用clang 3.2在线测试版本没有异议,但是MSVC,不走运,现在或以前你们都有很好的答案,目标一致,所以我很难决定接受哪个答案。相反,我将尝试进行更多测试,完善问题,看看是否有任何真正的编译器问题隐藏在这里。顺便说一句:模板typename std::enable_if::type//typename std::enable_if::type yakfun&&f{return f;}对于自由函数和lambda很好,而不是std::function,注释掉的带有decltype的行在我的Visual C++版本中不编译。第一个版本适用于自由函数和无状态lambda。你错过的那一秒是12月后的第二秒。除非我打错了,否则它应该可以与std::function配合使用。是的,需要偶尔清洁一下眼镜。IMO中有一个输入错误,应该是:typename std::enable_if::type,但即使这样也不行。编译器立即拒绝左侧为false,打印:错误C2039:“type”:不是带[\u Test=false,\u Ty=int]的“std::enable\u if”的成员,您正在使用哪个编译器?我对使用clang 3.2在线测试你的版本没有异议,但是MSVC,不走运,现在或以前关于你的编辑,检查可调用的返回值不是更好吗,就像在std::is_same::value中一样。这样,您就不会为实际的函数/函子类型而烦恼,不管它是对函数的引用、函数的指针、函子等等,只关心您是否可以通过给定返回类型的给定参数模式调用它。@chico-是的,这将非常好,并且符合Yakk的建议。不幸的是,你们要么运行其他编译器,要么我就要发疯了。我当然可以使用Clang3.2或g++4.8.0在LiveWorkspace上编译您和Yakko的代码版本,但不能使用Visual Studio。哦,好的,我使用的是Clang3.3。。。忘了msvc的事情。关于编辑,检查可调用函数的返回值不是更好吗,比如在std::is_same::value中。这样,您就不会为实际的函数/函子类型而烦恼,不管它是对函数的引用、函数的指针、函子等等,只关心您是否可以通过给定返回类型的给定参数模式调用它。@chico-是的,这将非常好,并且符合Yakk的建议。不幸的是,你们要么运行其他编译器,要么我就要发疯了。我当然可以使用Clang3.2或g++4.8.0在LiveWorkspace上编译您和Yakko的代码版本,但不能使用Visual Studio。哦,好的,我使用的是Clang3.3。。。忘了msvc的事了。
template <typename Fun>
typename std::enable_if<std::is_convertible<Fun, int(*)()>::value, int>::type 
template <typename Fun>
typename std::enable_if<std::is_convertible<decltype(std::declval<Fun>()()), int>::value>::type 
template <typename Fun>
auto MySh_Alpha(Fun&& f)->decltype( f() )
{ 
  return f();
}

template <typename Fun>
decltype( std::declval<Fun>()() ) MySh_Alpha2(Fun&& f)
{ 
  return f();
}