使用模板化的可变参数模板参数作为专用参数 [英] Use a templated variadic template parameter as specialized parameter

查看:457
本文介绍了使用模板化的可变参数模板参数作为专用参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的标题可能是错误的 - 如果是这样,请纠正我,但在某些时候我很难跟踪我实际尝试实现的元数据);



我有一个类功能模板,像这样:

  template< template< typename ...& MapType> 
Expression Expression :: substitute(MapType< std :: string,Expression> const& identifierToExpressionMap)const {
return SubstitutionVisitor< MapType>(identifierToExpressionMap).substitute
}

重要的是MapType。这个想法是允许 std :: map std :: unordered_map 随意插入。使用GCC和Clang,这是可行的,但Visual Studio 2013抛出编译错误:

错误C2664:'表达式表达式::替换< std :: map> (const MapType&)const':

不能将参数1从'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>和
1> [
1> _Kty = std :: string
1>,_Ty =表达式
1>] b
$ b 1>原因:不能从std :: map转换std :: string,Expression,std :: less< _Kty>,std :: allocator< std :: pair< const _Kty,_Ty> >>'to'const std :: map'

1>与
1> [
1> _Kty = std :: string
1>,_Ty =表达式
1>]

1>没有可以执行此转换的用户定义转换运算符,或者不能调用运算符

似乎MSVC不会把 MapType < std :: string,Expression>

所以我的问题是


  1. 这是可能的,只是MSVC中的一个错误,或

  2. 有一个更简单的方法。请记住,还有很多其他类可以接收 MapType 参数,并用不同的键/值类型实例化自己的版本。


    1. 解决方案

      这可能归结为:

        template  struct cat {}; 

      template< template< class ...> class Animal>
      void foo()
      {
      Animal< int> X; (void)x; //(A)
      }

      int main()
      {
      foo< cat>();
      }

      这个看起来很小的程序被clang ++和g ++接受, MSVC2013更新1。






      行(A)是有问题的:我认为在这个例子中,当传递类模板 cat 时,应当有两个模板参数。em template-parameter / p>

      看来,clang ++和g ++支持在行(A)中使用此模板的默认模板参数 template-parameter ,而MSVC 。



      我不知道标准是否要求其中一个;请参阅例如





      我肯定支持默认模板参数很有用,因为如在活动问题中所述),标准库的类模板可以具有附加的模板参数(具有默认参数);如果您想直接使用它们作为模板模板参数,您需要知道这些实现细节。


      My title might be wrong - if so, please do correct me, but at some point its hard for me to keep track of what meta thingy I'm actually trying to achieve ;)

      I have a class function template like this:

      template<template<typename...> class MapType>
          Expression Expression::substitute(MapType<std::string, Expression> const& identifierToExpressionMap) const {
              return SubstitutionVisitor<MapType>(identifierToExpressionMap).substitute(something);
          }
      

      The important part is the MapType. The idea is to allow either std::map or std::unordered_map to be plugged in at will. With GCC and Clang, this works, but Visual Studio 2013 throws a compilation error:

      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
      

      It seems that MSVC does not put MapType and <std::string, Expression> together as a type, am I missing something here?

      So my question is

      1. is this possible and just a bug in MSVC, or
      2. is there an easier way to do this. Please keep in mind that there are many other classes which receive the MapType parameter and instantiate their own version with different key/value Types.

      解决方案

      It probably boils down to this:

      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>();
      }
      

      This little innocent-looking program is accepted by clang++ and g++, but not by MSVC2013 Update 1.


      Line (A) is the problematic one: I think in this example it's clear that the template template-parameter Animal should have two template parameters, when passing the class template cat.

      It seems that clang++ and g++ support the use of default template arguments for this template template-parameter in line (A), while MSVC does not.

      I do not know if the Standard requires either of them; see for example

      It certainly appears to me that supporting the default template arguments is useful, since (as said in the active issue) the class templates of the Standard Library may have additional template parameters (with default arguments); and you'd need to know those implementation-details if you wanted to use them (directly) as template template-arguments.

      这篇关于使用模板化的可变参数模板参数作为专用参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆