boost::tuple
有一个get()
成员函数,如下所示:
tuple<int, string, string> t(5, "foo", "bar");
cout << t.get<1>(); // outputs "foo"
似乎C ++ 0x std::tuple
没有这个成员函数,你必须改为使用非成员函数形式:
std::get<1>(t);
对我来说,看起来更丑陋。
std::tuple
没有成员函数有什么特别的原因吗?或者只是我的实施(GCC 4.4)?
答案 0 :(得分:62)
来自C ++ 0x草案:
[注意:get是一个非成员函数的原因是,如果此功能是作为成员函数提供的,那么使用template关键字需要依赖于模板参数的类型的代码。 - 结束说明]
这可以通过以下代码来说明:
template <typename T>
struct test
{
T value;
template <int ignored>
T& member_get ()
{ return value; }
};
template <int ignored, typename T>
T& free_get (test <T>& x)
{ return x.value; }
template <typename T>
void
bar ()
{
test <T> x;
x.template member_get <0> (); // template is required here
free_get <0> (x);
};
答案 1 :(得分:27)
现有的答案很棒,而且标准委员会当然对此至关重要。但是我认为还有另一个问题很重要。
使用免费功能,您可以修改接口,而无需更改类的定义。您可以通过专门化全局get
来制作任何类型的“gettable”。使用成员函数,您必须直接修改类。
基于范围的for
在类类型上查找成员begin/end
,但它也通过ADL查找非成员begin/end
。这些API可以与任何容器一起使用,即使那些没有begin/end
功能的容器也可以使用。例如,您可以将它专门用于LibXML2元素类型,这样您就可以基于范围for
而不是xmlElement*
。
如果必须是成员函数,则不能这样做。
在C ++中,自由函数是许多操作的自然界面,可以在许多不同类上完成。
答案 2 :(得分:12)
N3090 / 3092,§20.4.2.6/ 8:“注意:get是非成员函数的原因是,如果此功能是作为成员函数提供的,那么依赖于模板参数的类型需要使用的代码模板关键字。-end note“