繁体   English   中英

使用模板化可变参数模板参数作为专用参数

[英]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::mapstd::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>放在一起作为一个类型,我在这里遗漏了什么?

所以我的问题是

  1. 这是可能的,只是MSVC中的一个错误,或者
  2. 是否有更简单的方法来做到这一点。 请记住,还有许多其他类接收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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM