在c++中,你能把根据模板调用的函数分开吗?

In c++ can you separate the function called based on the template?

我在 C++ 中有一个函数在理论上可以工作。我的意思是,如果函数被转换为像 Python 这样的语言,它会工作得很好,因为它没有被预编译。但是,在像 C++ 这样的语言中,它会抛出错误。

这是函数:

template <typename T>
T  JSONValue::get(){
    if(detect_number::detect<T> == true){
        if(type == JSONValueType::Number)
            return (T)number.value();
    }
    else if(detect_string::detect<T> == true){
        if(type == JSONValueType::String){return string.value();}
        return deparse(*this);
    }
    else if(detect_chararray::detect<T> == true){
        if(type == JSONValueType::String){return string.value().c_str();}
        std::string dep = deparse(*this);
        return dep.c_str();
    }
    else if(detect_boolean::detect<T> == true){
        if(!(type == JSONValueType::Boolean))
            return false;
        return boolean.value();
    }
    else if(is_specialization<T, std::vector>::value){
        if(type != JSONValueType::Array){
            std::cerr<<"must be an array to do this"<<std::endl;
            return T{};
        }
        T output;
        for(int i = 0; i < size(); i++){
        output.push_back(array.value().at(i).get<std::decay<decltype(*output.begin())>::type>());   
        }
        return output;
    }
    return T(0);
}

if 语句中,它检测传递的类型 T。如果它是一个数字,则执行此操作,如果它是一个向量,则执行此操作。

问题是,如果将矢量作为模板参数放入,则会抛出错误,因为无法将数字转换为矢量,等等。

有没有办法让编译器忽略错误,或者修复它,这样编译器就不必忽略它,它会 运行?

我记得前一段时间看到过如果类型是 typename 中的东西,那么 运行 这个函数,否则 运行 这个另一个函数。

在C++17及之后的版本中,可以使用if constexpr,例如:

if constexpr (detect_number::detect<T>){
    // T is a numeric type, do numerical things here...
}
else if constexpr (detect_string::detect<T>){
    // T is a string type, do stringy things here...
}
...

if 语句在运行时进行评估,因此整个函数在 compile-time 处必须在语法上正确,即使实际上只会使用其中的一部分。

但是,if constexpr 语句在 compile-time 处计算。因此,任何未使用的代码块都将被编译器删除,并且根本不会被评估。这将允许您在不同的 if constexpr 块中以不同的方式使用 T。编译器会将您的代码视为您编写的更像这样的代码:

// only when T is a number
template <typename T>
T JSONValue::get(){
    if(type == JSONValueType::Number)
        return (T)number.value();
    }
    return T(0);
}

// only when T is a string
template <typename T>
T JSONValue::get(){
    if(type == JSONValueType::String){return string.value();}
    return deparse(*this);
}

...

在 C++17 之前,您必须使用 SFINAE 或模板特化来完成同样的事情,例如:

// SFINAE 

template <typename T,
    typename std::enable_if<detect_number::detect<T>, bool>::type = true
>
T JSONValue::get(){
    if(type == JSONValueType::Number)
        return (T)number.value();
    return T(0);
}

template <typename T,
    typename std::enable_if<detect_string::detect<T>, bool>::type = true
>
T JSONValue::get(){
    if(type == JSONValueType::String){return string.value();}
    return deparse(*this);
}

...
// specialization

template <typename T>
T JSONValue::get(){
    return T{};
}

template<>
int JSONValue::get<int>(){
    if(type == JSONValueType::Number)
        return (T)number.value();
    return T(0);
}

template<>
std::string JSONValue::get<std::string>(){
    if(type == JSONValueType::String){return string.value();}
    return deparse(*this);
}

...