我的头衔可能是错的 - 如果是的话,请纠正我,但在某些时候我很难跟踪我实际上想要实现的东西;)
我有一个像这样的类函数模板:
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
参数,并使用不同的键/值类型实例化自己的版本。答案 0 :(得分:4)
这可能归结为:
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)是有问题的:我认为在这个例子中我很清楚模板 template-parameter Animal
应该有两个模板参数,当传递时课程模板cat
。
似乎clang ++和g ++支持在行(A)中使用此模板 template-parameter 的默认模板参数,而MSVC则不支持。
我不知道标准是否要求其中任何一个;例如,参见
在我看来,支持默认模板参数很有用,因为(如活动问题中所述)标准库的类模板可能有其他模板参数(使用默认参数);并且如果您想(直接)将它们用作模板模板参数,您需要了解这些实现细节。
答案 1 :(得分:1)
鉴于已经发生的讨论,我想也许是时候考虑解决方案了。由于推断模板模板参数似乎是手头的问题,因此放宽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。