与SFINAE一起在静态上加载

Cra*_*urg 2 c++ sfinae

我尝试在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正在使这两个案例中的一个出错,但我希望语言律师可以提供明确的答案.

T.C*_*.C. 5

令人惊讶的是,MSVC是正确的.(我知道,震惊.)[over.load]/p1-2:

1并非所有函数声明都可以重载.那里指定了那些不能重载的东西.如果程序在同一范围内包含两个这样的不可重载声明,则该程序格式不正确.[ 注意:此限制适用于范围中的显式声明,以及通过using-declaration(7.3.3)进行的此类声明和声明之间的声明.它不适用于由于名称查找而产生的函数集(例如,由于使用指令)或重载解析(例如,对于运算符函数).- 结束说明 ]

2某些函数声明不能​​重载:

  • 仅在返回类型上不同的函数声明不能​​重载.
  • 如果它们中的任何一个是成员函数声明(9.4),则不能重载具有相同名称和相同 parameter-type-liststatic成员函数声明.同样,如果其中任何一个是成员函数模板声明,则不能重载具有相同名称,相同 参数类型列表和相同模板参数列表的static成员函数模板声明.[...]
  • [...]

这两个bar()声明具有相同的名称,相同的参数类型列表和相同的模板参数列表,其中至少有一个是static,因此不能重载.