我尝试在Visual Studio 2013中编译以下程序并得到C2686: cannot overload static and non-static member functions错误.
#include <iostream>
#include <type_traits>
struct foo
{
template<bool P>
static std::enable_if_t<P> bar()
{
std::cerr << "P is true\n";
}
template<bool P>
std::enable_if_t<!P> bar()
{
std::cerr << "P is false\n";
}
};
int main()
{
foo f;
f.bar<true>();
}
Run Code Online (Sandbox Code Playgroud)
我熟悉这个编译器错误 - 请参阅此StackOverflow答案,但是很惊讶地发现错误与SFINAE一起,编译器将始终丢弃过载集中的两个重载中的一个.
Visual Studio 2013是否正确遵循此处的标准,或者是否可以与SFINAE一起使静态过载?
编辑:上面的对比示例与返回类型重载
如果没有SFINAE,则无法重载static,也无法在返回类型上重载.但是,Visual Studio 2013支持与SFINAE一起在返回类型上重载.
以下程序与上面的程序相同但删除static并更改了第二个foo::bar声明的返回类型,正确编译.
#include <iostream>
#include <type_traits>
struct foo
{
template<bool P>
std::enable_if_t<P> bar()
{
std::cerr << "P is true\n";
}
template<bool P>
std::enable_if_t<!P, int> bar()
{
std::cerr << "P is false\n";
return 42;
}
};
int main()
{
foo f;
f.bar<true>();
}
Run Code Online (Sandbox Code Playgroud)
在我看来,Visual Studio 2013正在使这两个案例中的一个出错,但我希望语言律师可以提供明确的答案.
令人惊讶的是,MSVC是正确的.(我知道,震惊.)[over.load]/p1-2:
1并非所有函数声明都可以重载.那里指定了那些不能重载的东西.如果程序在同一范围内包含两个这样的不可重载声明,则该程序格式不正确.[ 注意:此限制适用于范围中的显式声明,以及通过using-declaration(7.3.3)进行的此类声明和声明之间的声明.它不适用于由于名称查找而产生的函数集(例如,由于使用指令)或重载解析(例如,对于运算符函数).- 结束说明 ]
2某些函数声明不能重载:
- 仅在返回类型上不同的函数声明不能重载.
- 如果它们中的任何一个是成员函数声明(9.4),则不能重载具有相同名称和相同 parameter-type-list的
static成员函数声明.同样,如果其中任何一个是成员函数模板声明,则不能重载具有相同名称,相同 参数类型列表和相同模板参数列表的static成员函数模板声明.[...]- [...]
这两个bar()声明具有相同的名称,相同的参数类型列表和相同的模板参数列表,其中至少有一个是static,因此不能重载.