为什么tuple_size
是一个自由特征而不是类中的成员变量/ typedef?后者导致ODR违规的风险要小得多。
是否有一个具体的用例,其中特征tuple_size
比在类中定义此内联更好?是否存在类似于iterator_traits
(https://stackoverflow.com/a/6742025/5501675)的激励案例。我看到的唯一一个案例是它带来的不完整类型带来的好处。虽然不完全确定用例是什么
tuple_size
很容易成为像这样的成员
class Something {
public:
static constexpr auto tuple_size = 3;
};
然后tuple_size
特征的自由实现可以是
template <typename T, EnableIfHasTupleSize<std::decay_t<T>>* = nullptr>
struct tuple_size
: public std::integral_constant<std::size_t,
std::decay_t<T>::tuple_size>
{};
这样的实现既可以带来tuple_size
的好处,如果是专业的,可以使用不完整的类型,也可以在需要时提供成员的安全性。与iterator_traits
这个例子最近由@T.C.提供给我,说明tuple_size如何容易导致ODR违规。
struct X { int a; };
template<> struct std::tuple_size<X>;
template<size_t I> struct std::tuple_element<I, X> { using type = int; };
template<size_t I> int get(X) { return 1; }
call_func_that_checks_value_of_tuple_size(X{});
template<> struct std::tuple_size<X> : std::integral_constant<size_t, 3> {};
call_func_that_checks_value_of_tuple_size(X{});
编译器能够了解这一点,但是如果在翻译单元之间进行拆分,那么编译器很难抓住它。
答案 0 :(得分:2)
std::tuple
已在技术报告1中实施。
这是在C ++ 11存在之前,因此没有constexpr功能。由于std::tuple_size
是一个常量值,因此有必要使它成为一个模板,使其成为一个常量表达式(它可以完美地成为.size()
constexpr成员AFAIK而没有问题。)
对于非成员,std::array
也支持std::tuple_size
,任何结构都可以在理论上支持它。
所以我认为这些是决定的潜在原因,但我不知道背后的真正决定,我只是推理它。
答案 1 :(得分:2)
在C ++中,17结构化绑定需要类型支持std::tuple_size<T>
,启用ADL的get<std::size_t>
和std::tuple_element<std::size_t, T>
。
如果某个类型支持所有3,则结构化绑定可以正常工作。
这允许您使用第三方提供的类型,例如QPair,而无需修改其源代码或要求他们更新,在代码中以结构化绑定方式使用它。
如果tuple_size
是tuple
(以及array
和pair
)的成员,那么我们必须在C +中添加tuple_size
特征+17无论如何都有这种能力。
答案 2 :(得分:1)
一个可能的原因是std :: get的对称性(因为glorious C++ grammar而不能轻易成为成员)。