我有一个包含两个类似成员函数的类模板:
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引用,一个用于非const引用。我猜这个问题与顶级const限定符有关,但不能推断出如何解决它。
如何解决此问题,以便我仍然有两个版本的member()
并且模板会编译?
答案 0 :(得分:2)
当T
为int * const
时,T
已经const
,因此T&
和const T&
都是int * const
。< / p>
或者你的意思是在这种情况下,你需要你的班级看起来像:
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。
在以下代码中,member
的non_const版本将采用dummy_type
(指向成员函数的指针),如果T
已经是const。所以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
。它可以在g ++ 4.5.2下通过编译,启用C ++ 0x。但是我从来没有跑过它。
主要思想是,当T
是const时,成员的non_const版本采用任意类型的参数(一种不太可能在任何其他地方使用的类型,并且不太可能被隐式转换因此,non_const版本消失了。但顺便说一下,member
的实现中的逻辑中断(因为要使用参数类型,但不是预期的)。因此member
的主要逻辑是移动member_portal
的另一个函数。
答案 1 :(得分:2)
fefe给出的解释是正确的。 Foo const&
和Foo const 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 :(得分:0)
一个简单的解决方案是在T
为const
时禁用该功能:
#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);
};