我已经尝试过寻找这个,但我想到的每一个词都会产生完全不相关的结果。
我有一个函数(模板),它将指向成员的指针作为参数,但我似乎无法隐式地将指向的成员视为const。使用const_cast有效,但我想避免在可以的情况下明确地调用它。
struct MyStruct
{
int *_array;
int _size;
};
template<typename C, typename T>
void DoSomething(T* C::* arr, int siz)
{
// do some read-only stuff with the member here
}
template<typename C, typename T>
void ConstDoSomething(T* C::* arr, int siz)
{
DoSomething<C, T const>(arr, siz);
// DoSomething<C, T const>(const_cast<T const* C::*>(arr), siz); // works
}
MyStruct ms;
ConstDoSomething<MyStruct const, int>(&MyStruct::_array, ms._size); // note: cannot convert ‘arr’ (type ‘int* MyStruct::*’) to type ‘const int* MyStruct::*’
这是一个简化的示例,演示了我对更复杂的类树所遇到的问题。我试图避免演员,因为调用代码需要它(例如,使用类模板的人)。
更新:当我第一次发布此消息时,我意外地使用了未生成相同错误的代码示例。我花了相当多的测试来确定根本原因,那就是我在模板参数中添加了const限定符。上面的示例现在正确地演示了我正在使用的行为。
答案 0 :(得分:1)
您使用什么编译器?我已经尝试过您的代码Visual Studio 2012和2013,它编译时没有任何警告或错误。 无论哪种方式 - 当您使用constness
时,您应该尝试使用const_cast而不是static_cast答案 1 :(得分:0)
代替一个更好的解决方案(至少现在),我正在创建一个单独的重载来接受指向非const成员的指针,然后使用const_cast来调用原始方法。
如上所述,上面的示例是为了简单和清晰起见,但实际上我使用了几个类模板,每个模板继承自另一个,依此类推。这导致了以下相当丑陋的解决方案:
// C = containing class (for pointer-to-members, std::nullptr_t if none)
// T = type of data being referenced
template<typename _C, typename _T> struct MakeMemberPointer // STL doesn't provide this??
{
public:
typedef _T _C::* Type;
};
// Note: base-class template has specialization for C == std::nullptr_t
typedef typename std::conditional<std::is_same<C, decltype(nullptr)>::value,
T const* C::*,
T const*
>::type N;
typedef typename std::conditional<std::is_member_pointer<T>::value,
typename MakeMemberPointer<
C,
typename std::add_pointer<
typename std::remove_const<
typename std::remove_reference<
decltype(*(static_cast<C*>(nullptr)->*static_cast<N>(nullptr))) // T const&
>::type // reference removed -> T const
>::type // const removed -> T
>::type // pointer added -> T*
>::Type, // member pointer -> T* C::*
typename std::add_pointer<typename std::remove_const<typename std::remove_pointer<N>::type>::type>::type
>::type NNoConst;
void DoSomething(N t) noexcept
{
}
void DoSomething(NNoConst t) noexcept
{
DoSomething(const_cast<N>(t));
}
包含所有这些的类是一个从非const基类派生的const-only类(但由于模板参数,此处使用const成员)。在调用代码中使用const_cast时,在类中声明所有这一切是非常可取的(对我来说),但我仍然不明白为什么gcc不允许隐式地允许这种转换(毕竟,它只是添加< / strong> const限定符!!)。