匹配可变参数非类型模板 [英] Matching variadic non-type templates

查看:128
本文介绍了匹配可变参数非类型模板的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有两个结构, Foo Bar

Let's say I have two structs, Foo and Bar:

template<int...>
struct Foo{};

template<unsigned long...>
struct Bar{};

我想创建一个类型特征(称为 match_class )如果我通过两个 Foo< ...> 类型或两个 Bar< ...> 类型,但如果我尝试将它们混合使用则为false:

I want to create a type trait (call it match_class) that returns true if I pass two Foo<...> types or two Bar<...> types, but false if I try to mix them:

int main()
{
    using f1 = Foo<1, 2, 3>;
    using f2 = Foo<1>;
    using b1 = Bar<1, 2, 3>;
    using b2 = Bar<1>;
    static_assert(match_class<f1, f2>::value, "Fail");
    static_assert(match_class<b1, b2>::value, "Fail");
    static_assert(!match_class<f1, b1>::value, "Fail");
}

对于C ++ 1z(clang 5.0.0和gcc 8.0.0)足以做到这一点(演示):

For C++1z (clang 5.0.0 and gcc 8.0.0) it's sufficient to do this (Demo):

template<class A, class B>
struct match_class : std::false_type{};

template<class T, template<T...> class S, T... U, T... V>
struct match_class<S<U...>, S<V...>> : std::true_type{};

但是在C ++ 14中,出现以下错误(相同的编译器 * 演示):

But in C++14 I get the following error (same compilers* Demo):

error: class template partial specialization contains a template parameter that cannot be deduced; this partial specialization will never be used [-Wunusable-partial-specialization]
struct match_class<S<U...>, S<V...>> : std::true_type{};
       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
note: non-deducible template parameter 'T'
template<class T, template<T...> class S, T... U, T... V>



问题:在C ++ 14中,对此有什么解决方法?



理想情况下,用于测试类型特征的语法应保持不变。

Question: What is a workaround for this in C++14?

Ideally the syntax for testing the type trait should remain the same.

第二个问题: C ++ 14的行为是正确? (或者我未指定C ++ 17的行为吗?)

**请注意,MSVC 19.00.23506具有相同的失败演示

推荐答案

在C ++ 14中,您无法在以下情况中推断 T

In C++14, you could not deduce T in:

template<class T, template<T...> class S, T... U, T... V>
struct match_class<S<U...>, S<V...>> : std::true_type{};

但是在C ++ 17中,可以。您看到的行为是正确的。

but in C++17, you can. The behavior you see is correct.

在C ++ 14中,由于无法推断 T ,因此需要一个明确提供它的方式。因此,您可能需要类模板本身来指示其非类型模板参数类型:

In C++14, since you cannot deduce T, you need a way of explicitly providing it. So you might require the class templates themselves to indicate their non-type template parameter type:

template <int...> struct Foo { using type = int; };
template <unsigned long...> struct Bar { using type = unsigned long; };

或者对此具有外部特征。然后显式地写出所有内容-如果两个类模板具有相同的非类型模板参数,则它们匹配,并且也具有相同的类模板,顺序如下:

Or have an external trait for this. And then explicitly write out everything - two class templates match if they have the same non-type template parameter and then also have the same class template, in that order:

template <class... Ts> struct make_void { using type = void; };
template <class... Ts> using void_t = typename make_void<Ts...>::type;

template <class T1, class T2, class A, class B>
struct match_class_impl : std::false_type { };

template <class T, template <T...> class S, T... U, T... V>
struct match_class_impl<T, T, S<U...>, S<V...>> : std::true_type{};

template <class A, class B, class=void>
struct match_class : std::false_type { };

template <class A, class B>
struct match_class<A, B, void_t<typename A::type, typename B::type>>
    : match_class_impl<typename A::type, typename B::type, A, B>
{ };






这是对< a href = https://wg21.link/p0127 rel = noreferrer> 模板自动 。在C ++ 14中,[temp.deduct.type]包含:


This is a consequence of adding support for template auto. In C++14, [temp.deduct.type] contained:


不能从非类型的模板参数。 [示例:

template<class T, T i> void f(double a[10][i]);
int v[10][20];
f(v); // error: argument for template-parameter T cannot be deduced

-结束示例]

但是在C ++ 17中,它现在读取

But in C++17, it now reads:


当从表达式推导与用依赖类型声明的非类型模板参数 P 对应的参数,模板参数为 P 从值的类型推导。 [示例:

When the value of the argument corresponding to a non-type template parameter P that is declared with a dependent type is deduced from an expression, the template parameters in the type of P are deduced from the type of the value. [ Example:

template<long n> struct A { };

template<typename T> struct C;
template<typename T, T n> struct C<A<n>> {
  using Q = T;
};

using R = long;
using R = C<A<2>>::Q;           // OK; T was deduced to long from the
                                // template argument value in the type A<2>

-示例] N的类型 T [N] 类型的 std :: size_t [示例:

template<typename T> struct S;
template<typename T, T n> struct S<int[n]> {
  using Q = T;
};

using V = decltype(sizeof 0);
using V = S<int[42]>::Q;        // OK; T was deduced to std​::​size_­t from the type int[42]

结束示例]

这篇关于匹配可变参数非类型模板的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆