嵌套结构的专业化特征
Specialization traits of nested struct
我有一个带有嵌套模板结构的模板结构。
template <int F>
struct foo
{
template <int B>
struct bar {
static constexpr int f = F;
static constexpr int b = B;
};
};
我想创造一个像
这样的特质
template <class>
struct is_foo_bar : std::false_type { };
template <int F, int B>
struct is_foo_bar< foo<F>::bar<B> > : std::true_type { };
static_assert(is_foo_bar< foo<1>::bar<2> >::value);
这给出了一个错误:
type/value mismatch at argument 1 in template parameter list for ‘template<class> struct is_foo_bar’<br>
struct is_foo_bar<foo<F>::bar<B>> : std::true_type { };
如果我把bar
拿出来就好
template <int F, int B>
struct foo_bar {
static constexpr int f = F;
static constexpr int b = B;
};
template <int F>
struct foo
{
template <int B>
using bar = foo_bar<F, B>;
};
template <class>
struct is_foo_bar : std::false_type { };
template <int F, int B>
struct is_foo_bar< foo_bar<F, B> > : std::true_type { };
static_assert(is_foo_bar< foo<1>::bar<2> >::value);
...有效。但这不是我想要的方式。 bar
声明在 foo
?
中的代码中缺少什么
What I'm missing in code where bar
declaration is in foo
?
你在写偏特化时忘记了一个typename
和一个template
template <int F, int B>
struct is_foo_bar< typename foo<F>::template bar<B> > : std::true_type { };
// not deducible ^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^ deducible context
但真正的问题是第一个 int
模板值 F
在 ::
之前,因此无法推导。
您可以定义此部分专业化,但从未使用过。
用SFINAE可以这样解决
template <class, class = void>
struct is_foo_bar : std::false_type { };
template <class T>
struct is_foo_bar<
T,
std::enable_if_t<
std::is_same_v< T, typename foo<T::f>::template bar<T::b> >
>
> : std::true_type { };
这可行,但您需要显式指定所有参数,这可能是个问题(例如可变参数)。
编辑:找到可变参数的灵魂
template <int F>
struct foo
{
template <int B, class... Params>
struct bar {
static constexpr int f = F;
static constexpr int b = B;
static constexpr size_t size = sizeof...(Params);
};
};
template <class, class = void>
struct is_foo_bar : std::false_type { };
template <template <int, class...> class T, int B, class... Params>
struct is_foo_bar<
T<B, Params...>,
std::enable_if_t<
std::is_same_v<
T<B, Params...>,
typename foo< T<B, Params...>::f >::template bar<B, Params...>
>
>
> : std::true_type { };
template <int, class...>
struct not_foo_bar {
static constexpr int f = 0;
};
static_assert(is_foo_bar< foo<1>::bar<2> >::value);
static_assert(is_foo_bar< foo<1>::bar<2, int> >::value);
static_assert(not is_foo_bar< not_foo_bar<1> >::value);
static_assert(not is_foo_bar< not_foo_bar<1, int> >::value);
这确保 bar
属于 foo
。当没有这样的要求时,只用 std::void_t
和 std::declval
...
测试所需成员的存在应该不那么难看
我有一个带有嵌套模板结构的模板结构。
template <int F>
struct foo
{
template <int B>
struct bar {
static constexpr int f = F;
static constexpr int b = B;
};
};
我想创造一个像
这样的特质template <class>
struct is_foo_bar : std::false_type { };
template <int F, int B>
struct is_foo_bar< foo<F>::bar<B> > : std::true_type { };
static_assert(is_foo_bar< foo<1>::bar<2> >::value);
这给出了一个错误:
type/value mismatch at argument 1 in template parameter list for ‘template<class> struct is_foo_bar’<br>
struct is_foo_bar<foo<F>::bar<B>> : std::true_type { };
如果我把bar
拿出来就好
template <int F, int B>
struct foo_bar {
static constexpr int f = F;
static constexpr int b = B;
};
template <int F>
struct foo
{
template <int B>
using bar = foo_bar<F, B>;
};
template <class>
struct is_foo_bar : std::false_type { };
template <int F, int B>
struct is_foo_bar< foo_bar<F, B> > : std::true_type { };
static_assert(is_foo_bar< foo<1>::bar<2> >::value);
...有效。但这不是我想要的方式。 bar
声明在 foo
?
What I'm missing in code where
bar
declaration is infoo
?
你在写偏特化时忘记了一个typename
和一个template
template <int F, int B>
struct is_foo_bar< typename foo<F>::template bar<B> > : std::true_type { };
// not deducible ^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^ deducible context
但真正的问题是第一个 int
模板值 F
在 ::
之前,因此无法推导。
您可以定义此部分专业化,但从未使用过。
用SFINAE可以这样解决
template <class, class = void>
struct is_foo_bar : std::false_type { };
template <class T>
struct is_foo_bar<
T,
std::enable_if_t<
std::is_same_v< T, typename foo<T::f>::template bar<T::b> >
>
> : std::true_type { };
这可行,但您需要显式指定所有参数,这可能是个问题(例如可变参数)。
编辑:找到可变参数的灵魂
template <int F>
struct foo
{
template <int B, class... Params>
struct bar {
static constexpr int f = F;
static constexpr int b = B;
static constexpr size_t size = sizeof...(Params);
};
};
template <class, class = void>
struct is_foo_bar : std::false_type { };
template <template <int, class...> class T, int B, class... Params>
struct is_foo_bar<
T<B, Params...>,
std::enable_if_t<
std::is_same_v<
T<B, Params...>,
typename foo< T<B, Params...>::f >::template bar<B, Params...>
>
>
> : std::true_type { };
template <int, class...>
struct not_foo_bar {
static constexpr int f = 0;
};
static_assert(is_foo_bar< foo<1>::bar<2> >::value);
static_assert(is_foo_bar< foo<1>::bar<2, int> >::value);
static_assert(not is_foo_bar< not_foo_bar<1> >::value);
static_assert(not is_foo_bar< not_foo_bar<1, int> >::value);
这确保 bar
属于 foo
。当没有这样的要求时,只用 std::void_t
和 std::declval
...