如果我理解正确,您希望Print<V2, V1, V2, VB>::print(); 生成一个更易于理解的错误。
为此,我能想到的最好的办法就是与static_assert()s 合作。
在这种特殊情况下——Print 是一个 struct,只实现了部分专业化,没有实现通用版本——一个不是真的但简单的解决方案是可用的:实现通用版本以给出 static_assert() 错误带有您选择的消息。
举例
template <typename ... G>
struct Print
{
static_assert( sizeof...(G) == 0, "not same int container for Print<>");
static void print()
{ };
};
template <template<int> class ValueType, int ... Is>
struct Print< ValueType<Is>... >
{
static void print()
{
using unused = int const [];
(void)unused { (std::cout << Is, 0)... };
std::cout << std::endl;
}
};
不幸的是,这个解决方案接受为有效的Print<>;不知道对你有没有好处。
另一个(更好,恕我直言,但更精细)解决方案可以将Print 部分专业化转换为接受可变参数int 容器(可变参数ValueTypes 而不是固定ValueType)的专业化,并且在@ 987654332@,检查(使用自定义类型特征)所有容器是否相同。
举个例子,使用以下自定义类型特征
template <template <int> class ...>
struct sameCnts : public std::false_type
{ };
template <template <int> class C0>
struct sameCnts<C0> : public std::true_type
{ };
template <template <int> class C0, template <int> class ... Cs>
struct sameCnts<C0, C0, Cs...> : public sameCnts<C0, Cs...>
{ };
您可以编写Print 特化如下
template <template <int> class ... Cs, int ... Is>
struct Print< Cs<Is>... >
{
static_assert(sameCnts<Cs...>{}, "different containers in Print<>");
static void print()
{
using unused = int const [];
(void)unused { (std::cout << Is, 0)... };
std::cout << std::endl;
}
};
如果你会使用C++17,你可以使用折叠并且可以编写类型特征
template <template <int> class, template <int> class>
struct sameCnt : public std::false_type
{ };
template <template <int> class C>
struct sameCnt<C, C> : public std::true_type
{ };
template <template <int> class C0, template <int> class ... Cs>
struct sameCnts
: public std::bool_constant<(sameCnt<C0, Cs>::value && ...)>
{ };
和(在print()方法中也使用折叠)Print如下
template <template <int> class ... Cs, int ... Is>
struct Print< Cs<Is>... >
{
static_assert( sameCnts<Cs...>{}, "different containers in Print<>");
static void print()
{ (std::cout << ... << Is) << std::endl; }
};
-- 编辑--
OP 询问
但是我怎样才能让 Print 类也接受,例如,专门用于双非类型值而不是 int 非类型值的类型?
不确定你想要什么但是(记住double 值不能是模板非类型参数)我想你想要一个Print 接受具有非类型模板参数的类型,当此非类型模板参数的类型不像您的示例中那样固定 (int)。
对于 C++11 和 C++14,我认为有必要明确非类型值的类型。
我的意思是......如果你写Print如下
template <typename ...>
struct Print;
template <typename T, template <T> class ... Cs, T ... Is>
struct Print< T, Cs<Is>... >
{
static_assert(sameCnts<Cs...>{}, "different containers in Print<>");
// ...
};
你必须这样使用它
Print<int, V2, V1, V2, V3>::print();
这将int(或long,或其他)解释为第一个模板参数。这是因为无法推断出int 类型。
从C++17开始你可以使用auto作为非类型模板参数的类型,所以你可以写成Print如下
template <typename ...>
struct Print;
template <template <auto> class ... Cs, auto ... Is>
struct Print< Cs<Is>... >
{
static_assert( sameCnts<Cs...>{}, "different containers in Print<>");
static void print()
{ (std::cout << ... << Is) << std::endl; }
};
而且不需要明确类型,你可以写
Print<V2, V1, V2, V3>::print();
在这种情况下,您还必须在sameCnt 和sameCnts 中使用auto 而不是int。