首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >“懒人的enable_if”是合法的C++吗?

“懒人的enable_if”是合法的C++吗?
EN

Stack Overflow用户
提问于 2015-01-29 06:53:53
回答 2查看 4.1K关注 0票数 51

我经常使用一种我称之为“懒人的enable_if”的技术,在这种技术中,我使用decltype和逗号操作符来启用基于某些模板输入的函数。下面是一个小示例:

代码语言:javascript
复制
template <typename F>
auto foo(F&& f) -> decltype(f(0), void())
{
    std::cout << "1" << std::endl;
}

template <typename F>
auto foo(F&& f) -> decltype(f(0, 1), void())
{
    std::cout << "2" << std::endl;
}

使用--std=c++11,g++ 4.7+和Clang 3.5+愉快地编译了这段代码(它的工作方式正如我所期望的那样)。然而,当使用MSVC14 CTP5时,我得到这个错误,抱怨foo已经被定义了:

错误C2995:‘未知类型foo(F &&)':函数模板已定义c++-scratch main.cpp 15

所以我的问题是:“懒人的enable_if”是合法的C++,还是MSVC的bug?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-01-29 07:11:55

[temp.over.link]/6指定何时两个函数模板声明为重载。这是通过定义两个函数模板的等价性来实现的,如下所示:

如果两个函数模板..有返回类型..使用上述规则来比较涉及模板参数的表达式是等效的。

上面描述的“规则”是

如果包含两个表达式的两个函数定义满足一个定义规则(3.2),则认为这两个包含模板参数的表达式是等价的。

与本部分相关ODR在[basic.def.odr]/6中声明

给定在多个翻译单元中定义的名为D的实体,则

由相同的tokens;序列组成的 D 的定义

显然,由于返回类型(根据[dcl.fct]/2是尾随的返回类型)不包含相同的标记,因此包含这些表达式的两个函数定义将违反ODR。

因此,foo的声明声明了不等价的函数模板并重载了名称。

您看到的错误是由于VC++对表达式SFINAE的支持不足造成的--大概没有检查尾随返回类型的等价性。

解决方法

您可以通过另一种方式使函数模板不等价-更改模板参数列表。如果您像这样重写第二个定义:

代码语言:javascript
复制
template <typename F, int=0>
auto foo(F&& f) -> decltype(f(0, 1), void())
{
    std::cout << "2" << std::endl;
}

然后是VC++ compiles it fine。我缩短了temp.over.link/6中的引用,其中包括以下内容:

如果两个函数模板声明在相同的作用域中,具有相同的名称,具有相同的模板参数列表,则它们是等价的。

实际上,为了能够容易地引入新的重载,您可以使用一个小帮助器:

代码语言:javascript
复制
template <int I>
using overload = std::integral_constant<int, I>*;

用法是例如

代码语言:javascript
复制
// Remember to separate > and = with whitespace
template <typename... F, overload<0> = nullptr>
auto foo(F&&... f) -> decltype(f(0, 1)..., void())

template <typename... F, overload<1> = nullptr>
auto foo(F&&... f) -> decltype(f(0, 1, 2)..., void())

票数 44
EN

Stack Overflow用户

发布于 2015-01-29 07:01:38

这是一个称为"Expression SFINAE."的特性,但Visual C++还没有完全支持它(请参阅"C++11/14/17 Features In VS 2015 Preview",了解截至本文回答时的最新一致性更新)。

票数 33
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28203981

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档