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)没有?
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)没有?
来自C++0x草案:
[注:使用非成员函数的原因是,如果将此功能作为成员函数提供,则依赖于模板参数的类型的代码将需要使用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);
};
get
s是一个好主意。 - Christian Rau现有答案非常好,对于标准委员会来说当然至关重要。但我认为还有一个问题很重要,值得一提。
对于自由函数,您可以修改接口,而无需更改类的定义。您可以通过专门化全局 get
来使任何类型“可获取”。对于成员函数,您必须直接修改类。
基于范围的 for
在类类型上查找成员 begin/end
,但也通过 ADL 查找非成员 begin/end
。这些 API 可以用于任何容器,即使那些没有 begin/end
函数的容器也可以使用。您可以将其专门化为 LibXML2 元素类型,以便您可以在 xmlElement*
上进行基于范围的 for
。
如果必须是成员函数,则无法这样做。
在 C++ 中,自由函数是许多操作的自然接口,这些操作可能应用于许多不同种类的类。
std::begin/std::end
是成员函数和非成员函数优美协作的很好例子,你可以在大多数容器中使用任意一种。 - jakarN3090/3092, §20.4.2.6/8: "注意:get是一个非成员函数的原因是,如果将此功能作为成员函数提供,则依赖于模板参数类型的代码将需要使用模板关键字。—注释结束"