使用类属性

时间:2017-08-02 06:50:12

标签: c++ c++11 templates template-specialization non-type

假设您有一个名为enum class的{​​{1}},一个Func属性的类和一个包含函数模板Func的{​​{1}}类:

Functions

我想通过传递compute属性来调用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. } } 中相应的专用模板。但是,这不起作用,因为在编译时不知道Functions。我在func中收到以下错误:

func

我相信我可以通过在clang模板中设置candidate template ignored: invalid explicitly-specified argument for template parameter 'fn' ^ 方法并专门针对每个compute来实现这一目标:

Foo

然而,这违背了目的,因为我想使用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. 属性。另外,我想避免双重处理,因为func执行了一些操作,我必须将其复制到每个专门化中。

有没有办法通过使用Foo属性来实现此功能?

3 个答案:

答案 0 :(得分:3)

模板解析是一种完全编译时的机制。在这种情况下,你需要一些方法在运行时选择调用哪个函数:函数指针,虚函数,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.
        }
}

答案 1 :(得分:1)

您不必专门化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.
    }
};

答案 2 :(得分:1)

您无法使用模板解决此问题。模板解析附加和编译时间,您想要选择运行时。 有许多解决方案,例如提议的解决方案,但没有一个会使用模板。