我遇到了RValue不允许隐式转换的问题.我的问题是什么实施更好地“绕过”这个限制?
以下是用于说明问题的示例代码:
template<typename myVal>
class ITestClass
{
public:
virtual void myFunc(myVal item) = 0;
virtual myVal myFunc1() = 0;
};
class CTestClass : public ITestClass<int>
{
public:
void myFunc(int item) { }
int myFunc1() { return 0; }
};
template <typename T>
inline int CallFunction(std::shared_ptr< ITestClass<T> > ptrBase)
{
return 0;
}
inline std::shared_ptr< ITestClass<int> > GetBase()
{
return std::make_shared<CTestClass>();
}
std::shared_ptr< ITestClass<int> > ptrBase = std::make_shared<CTestClass>();
std::shared_ptr< CTestClass > ptrDerived = std::make_shared<CTestClass>();
CallFunction(ptrBase); // WORKS
CallFunction(GetBase()); // WORKS
CallFunction(std::make_shared<CTestClass>()); // ERROR
CallFunction(ptrDerived); // ERROR
可以使用RValue的所有调用,但函数需要基数,参数是派生失败.
选项1
选项1纠正问题:
CallFunction(std::static_pointer_cast< ITestClass<int> >(std::make_shared<CTestClass>()));
CallFunction(std::static_pointer_cast< ITestClass<int> >(ptrDerived));
此选项要求用户在调用函数之前将派生函数转换为基数.这有点失败了,因为它要求调用者知道转换的实际基类型(也就是具体的模板实例化基类型).
选项2
选项2纠正问题:
(修改模板和CallFunction一些)
template<typename myVal>
class ITestClass
{
public:
typedef myVal class_data_type;
virtual void myFunc(myVal item) = 0;
virtual myVal myFunc1() = 0;
};
class CTestClass : public ITestClass<int>
{
public:
void myFunc(int item) { }
int myFunc1() { return 0; }
};
template <typename T>
inline int CallFunction(std::shared_ptr<T> ptrBase)
{
static_assert(std::is_base_of<ITestClass<typename T::class_data_type>, T>::value, "Class needs to derive from ITestClass"); // some example of type checking
return 0;
}
CallFunction(std::make_shared<CTestClass>()); // now works as normal
CallFunction(ptrDerived); // now works as normal
我更喜欢选项2,因为调用者不知道RValue当前施加的限制但是我不确定是否有足够的类型检查static_asserts可以清除混淆,如果有人传递了错误的参数.
问题
>您认为选项2有什么问题,或选项1仍然是更好的路线?
>使用SFINAE有一种清洁类型安全的方法吗?
最佳答案 好吧,它与rvalues没有任何关系,而是与模板参数扣除失败有关.
模板参数匹配非常直接,就像简单的模式匹配一样.
以下是使用接口类中的typedef解决它的一种方法:
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
namespace our = boost;
template<typename myVal>
class ITestClass
{
public:
typedef myVal ValType;
virtual void myFunc(myVal item) = 0;
virtual myVal myFunc1() = 0;
};
class CTestClass : public ITestClass<int>
{
public:
void myFunc(int item) { }
int myFunc1() { return 0; }
};
template <typename T>
inline int CallFunctionAux(
our::shared_ptr< ITestClass<T> > ptrBase
)
{
return 0;
}
template< class T >
inline int CallFunction( our::shared_ptr< T > ptrBase )
{
return CallFunctionAux< typename T::ValType >( ptrBase );
}
inline our::shared_ptr< ITestClass<int> > GetBase()
{
return our::make_shared<CTestClass>();
}
int main()
{
our::shared_ptr< ITestClass<int> > ptrBase = our::make_shared<CTestClass>();
our::shared_ptr< CTestClass > ptrDerived = our::make_shared<CTestClass>();
CallFunction(ptrBase); // WORKS
CallFunction(GetBase()); // WORKS
CallFunction(our::make_shared<CTestClass>()); // WORKS
CallFunction(ptrDerived); // WORKS
}
干杯&心连心,