繁体   English   中英

使用类属性使用非类型模板参数调用模板函数

[英]Calling template function with non-type template parameter using class attribute

假设您有一个名为Funcenum class ,一个具有Func属性的类和一个包含函数模板computeFunctions类:

enum class Func
{
    Sin,
    Cos
    // Others...
}

class Functions
{
    public:

        template<Func fn>
        static inline double compute(const std::vector<double>& _args);
}

template<>
inline double compute<Func::Sin>(const std::vector<double>& _args)
{
    return std::sin(std::accumulate(_args.begin(), _args.end(), 0.0));
}


template<>
inline double compute<Func::Cos>(const std::vector<double>& _args)
{
    return std::cos(std::accumulate(_args.begin(), _args.end(), 0.0));
}

// More specialisations...

class Foo
{
    private:

        Func func;
        double result;

    public:

        inline void compute(const std::vector<double>& _args)
        {
            result = Functions::compute<func>(_args);
            // A few other operations follow.
        }
}

我想通过传递func属性从Functions调用适当的专用模板。 但是,这不起作用,因为在编译时不知道func 我在clang收到以下错误:

candidate template ignored: invalid explicitly-specified argument for template parameter 'fn'
                                       ^

我相信我可以通过将Foocompute方法也设为模板并专门针对每个Func来实现此目的:

class Foo
{
    private:

        Func func;
        double result;

    public:

        template<Func fn>       
        inline void compute(const std::vector<double>& _args)
        {
            result = Functions::compute<fn>(_args);
            // A few other operations follow.
        }
}

template<>
inline void compute<Func::Sin>()(const std::vector<double>& _args)
{
    result = Functions::compute<Func::Sin>(_args);
}

template<>
inline void compute<Func::Cos>()(const std::vector<double>& _args)
{
    result = Functions::compute<Func::Cos>(_args);
}

// Etc.

但是,这违反了目的,因为我想在Foo使用func属性。 另外,我想避免双重处理,因为Foo::compute()会执行更多操作,我必须将这些操作复制到每个专业化中。

是否可以通过使用func属性来实现此功能?

模板解析是一种完全编译时的机制。 在这种情况下,您需要某种方式在运行时选择调用哪个函数:函数指针,虚函数,switch语句...

使用函数指针的示例:

typedef double (*Func)(const std::vector<double>&);

double Sin(const std::vector<double>& args) {
    return std::sin(args[0]);
}
// etc.

class Foo
{
    private:

        Func func;
        double result;

    public:

        inline void compute(const std::vector<double>& _args)
        {
            result = func(_args);
            // A few other operations follow.
        }
}

您不必专门研究Foo::compute 您可以直接使用通用定义:

template<Func fn>       
void compute(const std::vector<double>& _args)
{
    result = Functions::compute<fn>(_args);
    // A few other operations follow.
}

如果要将运行时成员转换为编译时值,则必须分派自己。 switch或阵列是可能的方式

class Foo
{
private:

    Func func;
    double result;

public:

    void compute(const std::vector<double>& _args)
    {
        switch (func) {
        case Func::Sin: result = Functions::compute<Func::Sin>(_args); break;
        case Func::Cos: result = Functions::compute<Func::Cos>(_args); break;
        // ...
        }
        // A few other operations follow.
    }
};

您无法使用模板解决此问题。 模板解析追加和编译时间,您想选择一个运行时。 有很多解决方案,例如提出的解决方案,但是没有一个将使用模板。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM