模板函数实现中的条件取决于类型是否为指针

时间:2014-10-20 13:21:44

标签: c++ templates pointers

所以我有这个模板功能。 它应该在一个名为AbstractEvent的更复杂的结构中设置一个变量:

template< typename T >

void AbstractEvent::setVar( QString varName, T value) 
{
    if (std::is_pointer<T>::value)
    {
        void * castValue = static_cast<void*>(value);
        if (castValue)
        {
            //do sth with castValue
        }

     }
     else
     {
        //do something with value
     }
}

使用此模板功能,我想存储变量&#34; value&#34;在QVariant中然后将QVariant存储在某个地方。

如果&#34;价值&#34;是一个指针,我想将它存储为QVariant中的void *。对于其他任何我想存储真实类型的东西。

我尝试使用C ++ trait std :: is_pointer :: value来检查值是否为指针。

这段代码编译得很好,但是当我尝试使用它时,例如:

int intValue = 0;
setVar<int>("aVar",intValue);

我收到此错误:

error C2440: 'static_cast' : unable to convert from 'int' to 'void *'

我认为编译器很困惑,因为它正在检查这一行:

    void * castValue = static_cast<void*>(value);
当值不是指针时,

当然没有意义。这就是我的if语句

     if (std::is_pointer<T>::value)

本来应该避免,但是,即使在运行时,这段代码的值作为int也永远不会被执行,在编译时它会让编译器感到困惑......是否有解决这类问题的方法?

3 个答案:

答案 0 :(得分:5)

标签发送:

template< typename T >
void AbstractEvent::setVar_impl( QString varName, T value, std::true_type /*is_ptr*/) 
{
    void * castValue = static_cast<void*>(value);
    if (castValue)
    {
            //do sth with castValue
    }
}

template< typename T >
void AbstractEvent::setVar_impl( QString varName, T value, std::false_type /*is_ptr*/) 
{
    //do something with value
}

template< typename T >
void AbstractEvent::setVar( QString varName, T value){
    setVar_impl(varName, value, std::is_pointer<T>());
}

或者,过载然后SFINAE不适用:

template<typename T>
typename std::enable_if<std::is_pointer<T>::value>::type 
AbstractEvent::setVar(QString varName, T value) 
{
    void * castValue = static_cast<void*>(value);
    if (castValue)
    {
            //do sth with castValue
    }
}

template< typename T>
typename std::enable_if<!std::is_pointer<T>::value>::type 
AbstractEvent::setVar( QString varName, T value) 
{
    //do something with value
}

第三种选择,直接过载:

template< typename T >
void AbstractEvent::setVar( QString varName, T* value) 
{
    void * castValue = static_cast<void*>(value);
    if (castValue)
    {
            //do sth with castValue
    }
}

template< typename T >
void AbstractEvent::setVar( QString varName, T value) 
{
    //do something with value
}

第一个模板比第二个模板通过部分排序更专业化,因此如果两个模板同样可行则将被选择。

您可能还需要T == nullptr_t案例的特殊情况。 nullptr_t不是指针类型,但您可能希望在那种情况下调用指针重载。

答案 1 :(得分:4)

简单的重载,任何人?

template<typename T>
void AbstractEvent::setVar(QString varName, T value);

template<typename T>
void AbstractEvent::setVar(QString varName, T* value);

答案 2 :(得分:3)

您还可以使用std::conditional

来保持您的设计
typedef typename std::conditional<std::is_pointer<T>::value, void*, T>::type cast_type;
auto castValue = static_cast<cast_type>(value);

然而,使用标签调度或重载的解决方案 - 虽然更长 - 可能会更清晰一些。