[英]Use a templated variadic template parameter as specialized parameter
我的头衔可能是错的 - 如果是这样,请纠正我,但在某些时候我很难跟踪我实际上想要实现的东西;)
我有一个类函数模板,如下所示:
template<template<typename...> class MapType>
Expression Expression::substitute(MapType<std::string, Expression> const& identifierToExpressionMap) const {
return SubstitutionVisitor<MapType>(identifierToExpressionMap).substitute(something);
}
重要的部分是MapType。 这个想法是允许std::map
或std::unordered_map
随意插入。 使用GCC和Clang,这可行,但Visual Studio 2013会抛出编译错误:
error C2664: 'Expression Expression::substitute<std::map>(const MapType &) const' : cannot convert argument 1 from 'std::map<std::string,Expression,std::less<_Kty>,std::allocator<std::pair<const _Kty,_Ty>>>' to 'const std::map &' 1> with 1> [ 1> MapType=std::map 1> ] 1> and 1> [ 1> _Kty=std::string 1> , _Ty=Expression 1> ] 1> Reason: cannot convert from 'std::map<std::string,Expression,std::less<_Kty>,std::allocator<std::pair<const _Kty,_Ty>>>' to 'const std::map' 1> with 1> [ 1> _Kty=std::string 1> , _Ty=Expression 1> ] 1> No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
似乎MSVC没有把MapType
和<std::string, Expression>
放在一起作为一个类型,我在这里遗漏了什么?
所以我的问题是
MapType
参数,并使用不同的键/值类型实例化自己的版本。 它可能归结为:
template<class T, class U = int>
struct cat {};
template< template<class...> class Animal >
void foo()
{
Animal<int> x; (void)x; // (A)
}
int main()
{
foo<cat>();
}
这个看似无辜的小程序被clang ++和g ++接受,但不是MSVC2013 Update 1。
线(A)是有问题的:我认为在这个例子中很明显模板模板参数 Animal
在传递类模板cat
时应该有两个模板参数。
似乎clang ++和g ++支持在行(A)中使用此模板模板参数的默认模板参数,而MSVC则不支持。
我不知道标准是否要求其中任何一个; 例如,看看
在我看来,支持默认模板参数很有用,因为(如活动问题中所述)标准库的类模板可能有其他模板参数(使用默认参数); 如果你想(直接)使用它们作为模板模板参数 ,你需要知道那些实现细节。
鉴于已经发生的讨论,我想也许是时候考虑解决方案了。 由于推断模板模板参数似乎是手头的问题,因此放宽MapType的要求可能会有所帮助。
template< typename MapType>
Expression Expression::substitute( MapType const& identifierToExpressionMap) const {
return SubstitutionVisitor<MapType>(identifierToExpressionMap).substitute(something);
}
调用者将被编译为调用函数的编译代码,因此编译器将推导出模板参数,因此基本上你要将使用正确的std :: map或std :: unordered_map的责任推到调用者身上。
现在,至少在大多数情况下,这可能有效。 但是,可以传入某种编译但实际上没有正确类型的容器。 理想情况下,您仍然需要进行某种编译时检查以确保支持MapType(即:std :: map或std :: unordered_map)。
这可以通过Boost概念,或者甚至只有两个模板化的别名声明 - 使用enable_if可以确保别名声明只有两种版本:map或unordered_map。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.