c++ - 静态重载与 SFINAE 结合使用

标签 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>();
}

我熟悉这个编译器错误 — 请参阅 this StackOverflow answer , 但惊讶地看到与 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>();
}

在我看来,Visual Studio 2013 将这两种情况中的一种弄错了,但我希望语言律师可以提供明确的答案。

最佳答案

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

1 Not all function declarations can be overloaded. Those that cannot be overloaded are specified here. A program is ill-formed if it contains two such non-overloadable declarations in the same scope. [Note: This restriction applies to explicit declarations in a scope, and between such declarations and declarations made through a using-declaration (7.3.3). It does not apply to sets of functions fabricated as a result of name lookup (e.g., because of using-directives) or overload resolution (e.g., for operator functions). —end note]

2 Certain function declarations cannot be overloaded:

  • Function declarations that differ only in the return type cannot be overloaded.
  • Member function declarations with the same name and the same parameter-type-list cannot be overloaded if any of them is a static member function declaration (9.4). Likewise, member function template declarations with the same name, the same parameter-type-list, and the same template parameter lists cannot be overloaded if any of them is a static member function template declaration. [...]
  • [...]

两个bar()声明有相同的名字,相同的parameter-type-list,和相同的模板参数列表,至少其中一个是 static,因此不能重载。

关于c++ - 静态重载与 SFINAE 结合使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31062892/

相关文章:

c++ - C 库导出哪些函数?

c++ - 从 C++ 源文件创建全局变量列表

c++ - 类型推导后函数模板中的替换顺序是否有任何保证?

c++ - 检查类型是否被声明为元类型系统(对于 SFINAE)

c++ - 函数模板参数推导模板参数vs默认模板参数vs返回类型

c++ - 当模板重载可用时,检查函数的自定义重载是否存在

c++ - 优化是否应用于单行函数?

c++ - Qt Ui 存在但 Ui header 和源不存在

c++ - SFINAE 适用于扣除但因替代而失败

C++ 调试帮助内存泄漏