【问题标题】:c++ templated static class with a const array of function pointersc ++模板化静态类,带有函数指针的const数组
【发布时间】:2018-12-29 07:49:04
【问题描述】:

所以我真的需要一个具有以下结构的类,该类是模板化的,arr 是一个函数指针数组,但我似乎无法弄清楚正确的语法:

--myclass.h--

#include <vector>

template <typename T>
class MyClass {
    typedef void (*fptr)(std::vector<T> data);
    static void foo(std::vector<T> data);
    static void bar(std::vector<T> data);
    static void baz(std::vector<T> data);
    static const fptr arr[3];
};

--myclass.cpp--

#include "myclass.h"
#include <vector>

template <typename T> void MyClass<T>::foo(std::vector<T> data) { ... }
template <typename T> void MyClass<T>::bar(std::vector<T> data) { ... }
template <typename T> void MyClass<T>::baz(std::vector<T> data) { ... }

template <typename T> MyClass<T>::fptr MyClass<T>::arr[3] = { &foo, &bar, &baz };

如果有帮助,我的最终目标是让第四个成员函数从数组中调用 foobarbaz,这样我就可以避免多个 if-else 语句的开销(我的实际实现有接近 50 个这样的功能)。有没有更好的方法来做到这一点?

【问题讨论】:

  • 您有很多不相关的语法错误(额外的分号、额外的 static 关键字、不正确的 typedef、冲突的名称......)。在问你的问题之前解决这些问题。更好的是,提供一个可编译的示例并询问如何添加您想要的内容。
  • 你知道templates and headers,是吗?您确定要复制所有函数中的向量吗?

标签: c++ arrays templates static function-pointers


【解决方案1】:

fptr 被声明为const,因此也将其定义为const。另外,因为Sort是模板,所以需要typename引用MyClass&lt;T&gt;::fptr

template<typename T>
const typename MyClass<T>::fptr MyClass<T>::arr[] = { &foo, &bar, &baz };

附注:您不能将此定义或静态函数的定义放在源文件中,因为它们是模板。

Demo

此外,考虑使用using 代替typedef,并使用std::array 代替原始数组:

using fptr = void (*)(std::vector<T>);
static const std::array<fptr, 3> arr;
// [...]
template<typename T>
const std::array<typename MyClass<T>::fptr, 3> MyClass<T>::arr = { &foo, &bar, &baz };

Demo

有没有更好的方法来做到这一点?

可能,但我不能说没有更多关于你想要做什么的细节。

【讨论】:

  • 对于所有不相关的错误,我们深表歉意。希望我在编辑中修复了这些问题,以使事情更清晰。我只是不想复制粘贴 700 行代码。
  • 使用std::array 比使用原始数组有什么优势?
  • @KodyPuebla 与其他标准容器的一致接口......你得到迭代器,std::array 作为引用传递保留它的类型(而数组衰减为指针),所以 e。 G。大小仍然可用,...
  • @KodyPuebla 它的方法,它不会衰减为指针的事实,以及品味。没有任何开销。
【解决方案2】:

将整个类模板移动到 .hpp 文件中,并使用与声明相同的签名初始化 arr

template <typename T>
class MyClass {
    typedef void (*fptr)(std::vector<T> data);

    static void foo(std::vector<T> data) {}
    static void bar(std::vector<T> data) {}
    static void baz(std::vector<T> data) {}

    static const fptr arr[3];
};

template <typename T>
const typename MyClass<T>::fptr MyClass<T>::arr[] = { &foo, &bar, &baz };

你也可以直接定义arr

#include <iostream>
#include <vector>
#include <array>

template <typename T>
class MyClass {
    typedef void (*fptr)(std::vector<T> data);

    static void foo(std::vector<T> data) {
        for(int i : data) std::cout << "foo " << i << "\n";
    }
    static void bar(std::vector<T> data) {
        for(int i : data) std::cout << "bar " << i << "\n";
    }
    static void baz(std::vector<T> data) {
        for(int i : data) std::cout << "baz " << i << "\n";
    }
public:
    static constexpr std::array<fptr,3> arr = { &foo, &bar, &baz };
};

int main() {
    MyClass<int> a;
    a.arr[0](std::vector<int>(1));
    a.arr[1](std::vector<int>(2));
    a.arr[2](std::vector<int>(3));
}

输出:

foo 0
bar 0
bar 0
baz 0
baz 0
baz 0

【讨论】:

    【解决方案3】:

    您可以使用std::function 并将它们存储到向量中。到目前为止,这是我想出的。

    #include <exception>
    #include <iostream>
    #include <functional>
    #include <vector>
    
    template<typename T>
    class MyClass {
    private:
        std::vector<std::function<void(std::vector<T>)>> myFuncs_;
    
    public:
        MyClass() = default;
    
        void addFunc( std::function<void(std::vector<T>)> func ) {
            myFuncs_.push_back(func);
        }
    
        void caller(unsigned idx, std::vector<T> v ) {
            return myFuncs_.at(idx)( v );
        }
    
        static void foo(std::vector<T> data) {
            std::cout << "foo() called:\n";
    
            for (auto& d : data)
                std::cout << d << " ";
            std::cout << '\n';
        }
    
        static void bar(std::vector<T> data) {
            std::cout << "bar() called:\n";
    
            for (auto& d : data)
                std::cout << d << " ";
            std::cout << '\n';
        }
    };
    
    int main() {
        try {
            MyClass<int> myClass;
            std::vector<int> a{ 1,3,5,7,9 };
            std::vector<int> b{ 2,4,6,8,10 };
    
            std::function<void(std::vector<int>)> funcA = MyClass<int>::foo;
            std::function<void(std::vector<int>)> funcB = MyClass<int>::bar;
            myClass.addFunc( funcA );
            myClass.addFunc( funcB );
    
            myClass.caller(0, a);
            myClass.caller(1, b);       
    
        } catch( std::runtime_error& e ) {
            std::cerr << e.what() << std::endl;
            return EXIT_FAILURE;
        }
        return EXIT_SUCCESS;    
    }
    

    -输出-

    MyClass::foo() was called:
    1 3 5 7 9
    MyClass::bar() was called:
    2 4 6 8 10
    

    不确定这是否正是您想要的。在此示例中,MyClass::caller(...) 采用两个参数,即所需函数指针的向量的索引,以及函数需要作为输入的参数或数据。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-11-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多