【发布时间】:2017-10-31 00:04:33
【问题描述】:
假设我有两个结构,Foo 和 Bar:
template<int...>
struct Foo{};
template<unsigned long...>
struct Bar{};
我想创建一个类型特征(称为match_class),如果我传递两个Foo<...> 类型或两个Bar<...> 类型,则返回true,但如果我尝试混合它们,则返回false:
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),这样做就足够了(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 中,我收到以下错误(相同的编译器*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 中有什么解决方法?
理想情况下,测试类型特征的语法应该保持不变。
第二个问题:C++14 的行为是否正确? (或者我看到的 C++17 行为是否未指定?)
*注意,MSVC 19.00.23506 有同样的故障Demo
【问题讨论】:
-
它只适用于 GCC。很有趣。
-
更重要的是,它也适用于 clang 4.0.0。可能是 GCC 或 clang 中尚未实现的缺陷。
-
旁注 - 在 C++17 中你可以使用这个:
template<template<auto ...> class S, auto... U, auto... V> struct match_class<S<U...>, S<V...>> : std::true_type{};. -
@skypjack:说得好。我考虑过这个问题,但由于
auto模板参数的使用与 C++14 不兼容,我将其省略了:-)
标签: c++ templates c++14 variadic-templates non-type