2013-05-26 166 views
15

此代码中发生了什么?很混乱。- >函数原型意味着什么?

#include <utility> 

struct check 
{ 
    template <typename T> 
    auto foo() -> decltype(std::declval<T>().value, void()) 
    { 
     static_assert(T{}.value == 10, "Incorrect value"); 
    } 
} var; 

int main() 
{ 
    struct apple 
    { 
     int value{10}; 
    }; 

    var.foo<apple>(); 
} 

具体来说,它具有的部分->及其后的所有内容。

+2

- >是尾随返回类型。 'declval'是这个班级的一个实例。 'decltype'找到编译时表达式的类型。 'static_assert'是一个编译时断言。把它们拼凑在一起的时间:) – chris

+3

含糊不清的标题不会对其他有相同问题的人有用。 –

+1

@RiaD:虽然标题编辑更有帮助,但它仍然不准确 - 他似乎在询问特定用途。 –

回答

10

让我们一点一点地经历。

auto foo() -> decltype(std::declval<T>().value, void()) 

这是一个尾随返回类型。允许使用参数,但这里没有必要。我想这是写得更清晰。 decltype找到里面的表达式的类型,但该表达式实际上没有被评估。 std::declval用于创建传递给它的类型的实例。这里使用逗号运算符来使总体返回类型void,因为逗号运算符评估左侧,将其抛出,评估右侧并返回该结果。

第一部分创建了一种SFINAE(尽管我从来没有见过它是这样使用的)。例如,如果您的foo的过载与value2的过载相同,而不是value,则不会含糊不清。我的意思是here。将其与this one进行比较,其返回类型为void,并导致错误。

static_assert(T{}.value == 10, "Incorrect value"); 

此行确保如果没有的话,会产生与文本编译器错误的T值初始化实例都有value成员有值10。

} var; 

这只是该类使用的全局对象。

struct apple 
{ 
    int value{10}; 
}; 

这是一个样本类来测试它。它有一个value成员,该成员在值初始化的实例中也是10(也是默认初始化的)。

var.foo<apple>(); 

这只是调用函数。

+0

当我做'struct grape {}; var.foo ();'它给我一个错误。我怎么能让它默默地失败? –

+0

@MemyselfandI,你需要有一个适用于葡萄等结构的'foo'版本。问题是你必须确保用'apple'调用它并不含糊。我会尽力准备一个例子。 – chris

+0

@MemyselfandI,非常感谢Xeo,[你在这里](http://coliru.stacked-crooked.com/view?id=200ce7dd4c270d3bfdea6df8628f6e4e-8a676986784bd3a58ce3ec015645a41f)。这是你可以根据类型是否具有'value'数据成员来实现'foo'的地方。 – chris