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

condition in template function implementation depending on whether the type is a pointer

本文关键字:取决于 类型 是否 指针 函数 实现 条件      更新时间:2023-10-16

所以我有这个模板函数。它应该在一个更复杂的结构中设置一个变量,称为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
     }
}

使用这个模板函数,我想将变量"value"存储在QVariant中,然后将QVariant存储在某个地方。

如果"value"是一个指针,我想把它作为一个void*存储在QVariant中。对于其他任何东西,我都想存储真正的类型。

我尝试使用C++特性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的代码永远不会被执行,在编译时,它也会混淆编译器。。。这类问题有解决办法吗?

标记调度:

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>());
}

或者,过载,然后清除不适用的

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不是指针类型,但您可能希望在这种情况下调用指针重载。

简单的重载,有人吗?

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

您也可以使用std::conditional:来保留您的设计

typedef typename std::conditional<std::is_pointer<T>::value, void*, T>::type cast_type;
auto castValue = static_cast<cast_type>(value);

然而,使用标记调度或重载的解决方案——尽管时间更长——可能更清晰一些。