使用typeid分隔代码执行

Tho*_*son 1 c++ templates types

这个问题源于需要调用传统的C例程(FFTW),它们在模板化的C++类中具有不同的函数名称,具体取决于类型(单/双/四倍精度).这个错误的代码示例给出了我可能想要做的一个简单示例:

#include <cstdio>
#include <cmath>
#include <typeinfo>
#include <cstdlib>

void fcnd(double *x) {
    *x = pow(*x, 2);
    printf("%f\n", *x);
}

void fcnf(float *x) {
    *x -= 1;
    printf("%f\n", *x);
}

template <typename T> class Class {

public:
    void fcn() {
        T *var;
        if (typeid(T) == typeid(float)) {
            var = (float *) malloc(sizeof(float));
        } else if (typeid(T) == typeid(double)) {
            var = (double *) malloc(sizeof(double));
        }

        *var = 1.0;

        if (typeid(T) == typeid(float)) {
            fcnf(var);
        } else if (typeid(T) == typeid(double)) {
            fcnd(var);
        }
        free(var);
    }
};

int main() {
    Class<double> x;
    Class<float> y;

    x.fcn();
    y.fcn();
}
Run Code Online (Sandbox Code Playgroud)

海湾合作委员会抱怨:

test.cpp: In instantiation of 'void Class<T>::fcn() [with T = double]': test.cpp:42:11:   required from here test.cpp:22:17: error: cannot convert 'float*' to 'double*' in assignment
             var = (float *) malloc(sizeof(float));
                 ^ test.cpp:30:17: error: cannot convert 'double*' to 'float*' for argument '1' to 'void fcnf(float*)'
             fcnf(var);
                 ^ test.cpp: In instantiation of 'void Class<T>::fcn() [with T = float]': test.cpp:43:11:   required from here test.cpp:24:17: error: cannot convert 'double*' to 'float*' in assignment
             var = (double *) malloc(sizeof(double));
                 ^ test.cpp:32:17: error: cannot convert 'float*' to 'double*' for argument '1' to 'void fcnd(double*)'
             fcnd(var);
                 ^
Run Code Online (Sandbox Code Playgroud)

现在,我知道这里的错误是什么.我的问题是,为什么C++不允许这样做?当然这是安全的,对吧?我认为专业化在这里可能有所帮助,总是正确的方法吗?

use*_*177 5

在C++ 17中,可以按如下方式调用基于模板参数的函数:

template <typename T> class Class
{
public:
    void fcn()
    {
        // one line can do it
        T* var{ reinterpret_cast<T*>(std::malloc(sizeof(*var))) };

        *var = 1.0;

        // C++17's if constexpr does exactly what you need
        if constexpr (std::is_same_v<T, float>)
        {
            fcnf(var);
        }
        else if constexpr (std::is_same_v<T, double>)
        {
            fcnd(var);
        }

        free(var);
    }
};
Run Code Online (Sandbox Code Playgroud)

如果您没有可用的C++ 17,则可以使用基于T模板特化的调度程序或仅使用简单的重载函数.

auto set(float* f) noexcept
{
    return fcnf(f);
}

auto set(double* d) noexcept
{
    return fcnd(d);
}

template <typename T> class Class
{
public:
    void fcn() 
    {
        T* var{ reinterpret_cast<T*>(std::malloc(sizeof(*var))) };
        *var = 1.0;
        set(var); // there's a reason we have function overloading in C++
        free(var);
    }
};
Run Code Online (Sandbox Code Playgroud)

注意:我希望在您的真实代码中检查调用的结果std::malloc().