我正在尝试开发一个通用代码,可以选择不同的容器类型(std::vector
,std::map
,other),并对该容器包装器执行操作,但我遇到了以下代码:
enum class EContainnerType
{
EContainnerType_Normal,
EContainnerType_OR,
EContainnerType_AND
};
// Base declaration
template<EContainnerType, template<class ... > class ContainerType, class ... ArgType >
struct ConditionContainnerType
{
};
// Partial Specialization
template< template<class ... > class ContainerType, class ... ArgType >
struct ConditionContainnerType<EContainnerType::EContainnerType_OR, ContainerType<ArgType ... >, ArgType ...>
{
};
int main()
{
return 0;
}
可变参数模板模板参数无法编译,我收到此错误:
main.cpp:33:108: error: wrong number of template arguments (2, should be 3)
struct ConditionContainnerType<EContainnerType::EContainnerType_OR,typename ContainerType<ArgType>, ArgType>
^
main.cpp:29:8: error: provided for 'template<EContainnerType <anonymous>, template<class> class ContainerType, class ArgType> struct ConditionContainnerType'
struct ConditionContainnerType
目标:
此实现的主要目标是执行某种分类操作(OR,AND,XOR),此操作在与通用容器进行比较的元素上执行。
操作类型由enum class
定义,并选择部分特化来执行操作。
所以,如果我有一个集合{a,b,c,d,e}
并且我用特定的元素组合填充集合说:
generic_container<Operation_type,generic_set_element>
然后我希望通用条件容器执行&#34;操作类型&#34; 选择的操作。
因此,如果将元素x
与集合进行比较,则通用容器可以对x
元素执行预先选择的操作。
答案 0 :(得分:3)
你的编译器坏了。正确的错误消息如下所示(g ++ 4.8.2)
error: type/value mismatch at argument 2 in template parameter list for ‘template<EContainnerType <anonymous>, template<class ...> class ContainerType, class ... ArgType> struct ConditionContainnerType’
struct ConditionContainnerType<EContainnerType::EContainnerType_OR,ContainerType<ArgType ... >,ArgType ...>
^
error: expected a class template, got ‘ContainerType<ArgType ...>’
或者这个(铿锵3.3)
error: template argument for template template parameter must be a class template or type alias template
struct ConditionContainnerType<EContainnerType::EContainnerType_OR,ContainerType<ArgType ... >,ArgType ...>
^
他们非常不言自明。
所以只需删除参数。
//Partial Specialization
template< template<class ... > class ContainerType, class ... ArgType >
struct ConditionContainnerType<EContainnerType::EContainnerType_OR,
ContainerType, ArgType ...>
{
};
现在你可以写
了ConditionContainnerType<EContainnerType::EContainnerType_OR, std::vector, int> a;
ConditionContainnerType<EContainnerType::EContainnerType_OR, std::map, int, int> b;
无需重复参数两次。
答案 1 :(得分:1)
问题在于,您无法使用给定模板参数的 template-template参数专门化 template-template 参数,例如强制:
ContainerType<Args...>
匹配:
template <typename...> class BaseContainerType
因为它不再是模板模板参数。相反,此处需要使用普通的ContainerType
名称,而不需要<Args...>
部分:
// Base declaration
template <template <typename...> class ContainerType>
struct ConditionContainnerType
{
};
// Partial specialization for two-parameter template template parameter
template <template <typename, typename> class ContainerType>
struct ConditionContainnerType<ContainerType>
{
};
但是,您可以使用填充了参数的 template-template 参数来专门化模板类型本身(即使使用扩展的参数包),如下所示:
// Base declaration
template <EContainnerType, typename ContainerType, typename... Args>
// ^^^^^^^^^^^^^^^^^^^^^^^ normal type here
struct ConditionContainnerType
{
};
// Partial specialization
template <template <typename...> class ContainerType, typename... Args>
// ^^^^^^^^ template here
struct ConditionContainnerType<EContainnerType::EContainnerType_OR,
ContainerType<Args...>,
// ^^^^^^^ expanded parameter pack
Args...>
{
};
或没有尾随参数包:
template <template <typename...> class ContainerType, typename... Args>
struct ConditionContainnerType<EContainnerType::EContainnerType_OR,
ContainerType<Args...>>
{
};
以及为std::vector<T, A>
这样的模板化容器专门设置它,这些容器只有两个参数:type T
and allocator A
:
template <template <typename, typename> class ContainerType, typename T, typename A>
struct ConditionContainnerType<EContainnerType::EContainnerType_OR,
ContainerType<T, A>,
T>
{
};
<强> 试验: 强>
int main()
{
// base, AND does not match OR
ConditionContainnerType<EContainnerType::EContainnerType_AND
, MyContainer<int>
, int>{};
// specialized, OR and parameter pack matches
ConditionContainnerType<EContainnerType::EContainnerType_OR
, MyContainer<int>
, int>{};
// base, OR matches, but parameters packs do not
ConditionContainnerType<EContainnerType::EContainnerType_OR
, MyContainer<float>
, int>{};
// vector, OR and parameter pack matches
ConditionContainnerType<EContainnerType::EContainnerType_OR
, std::vector<int>
, int>{};
// OR and no parameter-pack
ConditionContainnerType<EContainnerType::EContainnerType_OR
, std::vector<int>>{};
}
如果不是这样,你的目标是根据具体的容器类型(std::vector
,std::map
)来专门化你的基本声明,你可以这样做:
// Base declaration
template <EContainnerType, template <typename...> class ContainerType>
struct ConditionContainnerType
{
};
// Partial specialization for std::vector
template <>
struct ConditionContainnerType<EContainnerType::EContainnerType_OR, std::vector>
// ^^^^^^^^^^^
{
};
// Partial specialization for std::map
template <>
struct ConditionContainnerType<EContainnerType::EContainnerType_AND, std::map>
// ^^^^^^^^
{
};
<强> 试验: 强>
int main()
{
// First specialization
ConditionContainnerType<EContainnerType::EContainnerType_OR, std::vector>{};
// Second specialization
ConditionContainnerType<EContainnerType::EContainnerType_AND, std::map>{};
}