【问题标题】:How to resolve this issue with top-level const?如何用顶级 const 解决这个问题?
【发布时间】:2011-12-13 07:18:25
【问题描述】:

我有一个包含两个相似成员函数的类模板:

template<class T>
class MyTemplate {
   // other stuff, then
   static T* member( T& ); //line 100
   static const T* member( const T& ); //line 101

};

我这样实例化:

MyTemplate<int* const>

Visual C++ 9 抱怨:

mytemplate.h(101) : error C2535: 'int* MyTemplate<T>::member(T &)' :
   member function already defined or declared
with
[
    T=int *const 
]
mytemplate.h(100) : see declaration of 'MyTemplate::member'
with
[
    T=int *const 
]
somefile.cpp(line) : see reference to class template instantiation
    'MyTemplate<T>' being compiled
with
[
    T=int *const 
]

我当然需要member() 的两个版本——一个用于常量引用,一个用于非常量引用。我猜这个问题与顶级 const 限定符有关,但无法推断出如何解决它。

如何解决这个问题,以便我仍然有两个版本的member() 并且模板可以编译?

【问题讨论】:

    标签: c++ templates visual-c++ constants


    【解决方案1】:

    fefe 给出的解释是正确的。 Foo const&amp;Foo const const&amp; 将简单地评估为相同的类型,因此您的函数重载不起作用。如果您的模板参数是 const,我建议您进行专业化。

    版本 A:

    template<class T>
    class MyTemplate {
       static T* member( T& );
       static const T* member( const T& );
    };
    template<class T>
    class MyTemplate<T const> {
       static const T* member( const T& );
    };
    

    B 版:

    template<class T>
    class MyTemplate_mutableImpl {
       static T* member( T& );
    };
    template<class T>
    class MyTemplate_constImpl {
       static const T* member( const T& );
    };
    template<class T>
    class MyTemplate : public MyTemplate_mutableImpl<T>, public MyTemplate_constImpl<T> {
    };
    template<class T>
    class MyTemplate<T const> : public MyTemplate_constImpl<T const> {
    };
    

    【讨论】:

      【解决方案2】:

      Tint * const 时,T 已经是const,所以T&amp;const T&amp; 都是int * const

      或者你的意思是在这种情况下,你需要你的类看起来像:

      class MyTemplate_int_p_const{
           static int * member (int *&);
           static int * const member (int * const &);
      };
      

      您可以将此添加到您的主模板中以实现此目的:

      template<class T>
      class MyTemplate<const T>
      {
          static T * member(T&);
          static const T* member(const T&);
      };
      

      作为对 OP 评论的回应,如果您不想使用部分专业化,则需要 type_traits。 C++0x支持,VC++9可以使用boost

      在下面的代码中,如果 T 已经是 const,则 member 的非 const 版本将采用 dummy_type(指向成员函数的指针)。所以 non_const 重载将不存在。

      #include <type_traits>
      template<class T>
      class MyTemplate {
         // other stuff, then
      
         //void dummy(void);
         typedef void (*dummy_type)(void);
         typedef typename std::conditional<std::is_const<T>::value, dummy_type, T>::type T_no_const;
         typedef typename std::remove_const<T>::type T_remove_const;
         static T_no_const* member( T_no_const& t ) //line 100
         {
             if (std::is_same<T, T_no_const>::value)
             {
                 return member_portal(t);
             }
             else
                 return NULL;
         }
         static T_no_const* member_portal(dummy_type&){return NULL;};
         static T_remove_const* member_portal(T_remove_const&);
         static const T* member( const T& ); //line 101
      
      };
      
      
      int main()
      {
          MyTemplate<int * const> mt;
          MyTemplate<int *> mtt;
          return 0;
      }
      

      这是我第一次玩type_traits。它可以在启用 C++0x 的 g++ 4.5.2 下通过编译。但我从来没有运行过。

      主要思想是,当T 是 const 时,成员的 non_const 版本采用任意类型的参数(这种类型不太可能在其他任何地方使用,也不太可能被隐式转换为) ,因此 non_const 版本消失了。但是顺便说一句,member 的实现中的逻辑中断了(因为要使用参数类型,但不是预期的)。所以member的主要逻辑是移动member_portal的另一个函数。

      【讨论】:

      • T 是 const 时,我宁愿只使用 const 版本。这可能吗?
      • @sharptooth 当然要去掉偏特化中member的非常量版本。
      • 我的模板实际上大约有一百个成员 - 部分专业化的想法听起来并不酷。
      • @sharptooth 在这种情况下,您需要使用 type_traits。它由 c++0x 支持。我认为您可以在 VC++9 中找到等效的 boost。
      【解决方案3】:

      如果Tconst,则一个简单的解决方案是禁用该功能:

      #include <boost/mpl/if.hpp>
      #include <boost/type_traits/is_const.hpp>
      
      template<class T>
      class MyTemplate {
         static T* member( T& );
         struct Disabled {};
         static const T* member(typename boost::mpl::if_<boost::is_const<T>, Disabled, const T&>::type);
      };
      

      【讨论】:

        猜你喜欢
        • 2023-04-06
        • 1970-01-01
        • 2014-10-07
        • 1970-01-01
        • 2020-04-27
        • 2019-10-13
        • 1970-01-01
        相关资源
        最近更新 更多