开发者

Proper Implementation in the midst of no RValue implicit conversion

I ran into the problem that RValue does not allow implicit conversion. My questions is what implementation is better to "bypass" this limitation?

Here is example code to illustrate the issue:

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

All calls where RValue could be utilized but the function wants the base and the parameter is the derived fail.

Option 1

Option 1 to correct the issue:

CallFunction(std::static_pointer_cast< ITestClass<int> >(std::make_shared<CTestClass>()));
CallFunction(std::static_pointer_cast< ITestClass<int> >(ptrDerived));

This option requires the user to cast the derived into the base before calling the function. This defeats the purpose some because it requires the caller to know the actual base type for the conversion (aka what concrete template instantiation base type it is).

Option 2

Option 2 to correct the issue: (modify the template and CallFunction some)

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

I like option 2 better because callers don't know the limitation that 开发者_Python百科is currently imposed with RValue but I am not sure if there are enough typechecking static_asserts that would clear up the confusion if someone passes the wrong parameter.

Questions

  1. Do you see anything wrong with Option 2 or is Option 1 still the better route?

  2. Using SFINAE is there a way to clean the type safety?


Well, it doesn't have anything to do with rvalues, but rather with template parameter deduction failure.

Template parameter matching is very very direct, like a simple pattern matching.

The following is one way to resolve it, using a typedef in the interface class:

#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
}

Cheers & hth.,

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜