我有一个班Foo和 class 酒吧 . 它们是std :: array的包装器 . 它们都有一些派生类 .
template<typename T, std::size_t N>
struct Foo {
std::array<T, N> data;
};
template<typename T, std::size_t N>
struct FooDerived : Foo <T, N> {};
template<typename T, std::size_t N>
struct Bar {
std::array<T, N> data;
};
template<typename T, std::size_t N>
struct BarDerived : Bar <T, N> {};
我想在std命名空间中实现tuple-interface:get / tuple_size / tuple_element . 但是这些方法对于Foo应该是 only ,并且可以从Foo类派生 .
namespace std {
template<template<typename, std::size_t> class T, typename TArg, std::size_t NArg>
class tuple_size<T<TArg, NArg>>
: public integral_constant<std::size_t, NArg>
{
};
template<std::size_t I, template<typename, std::size_t> class T, typename TArg, std::size_t NArg>
struct tuple_element<I, T<TArg, NArg>>
{
using type = TArg;
};
} // namespace std
这有效,但也适用于Bar和Bar派生类 .
我想用std :: enable_if和std :: is_base_of . 类的std :: enable_if可以用作模板参数 . 如果我写:
template<template<typename, std::size_t> class T, typename TArg, std::size_t NArg,
typename std::enable_if<std::is_base_of<Foo<TArg, NArg>, T<TArg, NArg>>::value, int>::type = 0>
class tuple_size<T<TArg, NArg>>
: public integral_constant<std::size_t, NArg>
{
};
它导致编译错误:默认模板参数可能不会用于部分特化 .
是否有可能禁止使用类似于元组的接口来与Foo类无关?
示例:http://rextester.com/JEXJ27486
Update: 似乎我找到了解决方案 . 比static_assert更灵活 . 如果在部分特化中无法使用默认模板参数 - 请添加具有完整模板特化的其他类 .
template<typename T, typename TArg, std::size_t NArg, typename = void>
struct tuple_resolver;
template<typename T, typename TArg, std::size_t NArg>
struct tuple_resolver<T, TArg, NArg,
typename std::enable_if<std::is_base_of<Foo<TArg, NArg>, T>::value>::type>
: public integral_constant<std::size_t, NArg>
{
using type = TArg;
};
template<template<typename, std::size_t> class T,
typename TArg,
std::size_t NArg>
class tuple_size<T<TArg, NArg>>
: public tuple_resolver<T<TArg, NArg>, TArg, NArg>
{
};
3 回答
如果你可以使用提议但尚未标准化的语言功能,这似乎可以在带有
-fconcepts
标志的gcc 6.1下工作:一个好老
static_assert()
怎么样?如果您想为不同的派生组类型使用不同的
tuple_size
类,我的先前解决方案(基于static_assert()
)不起作用 .我建议基于
std::conditional
和std::is_base_of
的以下解决方案棘手(而且很丑陋,我猜)部分是
struct
baseType
,如果可能的话,给定一个类型,检测一个基数(在Foo
和Bar
之间) .