шаблонный статический класс c ++ с константным массивом указателей на функции - PullRequest
0 голосов
/ 29 декабря 2018

Так что мне действительно нужен класс со следующей структурой, где класс является шаблонным, а 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 };

Если это поможет, моя конечная цель - чтобы четвертая функция-член вызывала либо foo, bar или baz из массива, чтобы я мог избежать накладных расходов на несколько операторов if-else (моя фактическая реализация ближе к 50 из этих функций).Есть ли лучший способ сделать это?

Ответы [ 3 ]

0 голосов
/ 29 декабря 2018

Переместите весь шаблон класса в файл .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
0 голосов
/ 29 декабря 2018

Вы можете использовать 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;    
}

-Output-

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

Не уверен, что это именно то, что вы искали.В этом примере MyClass::caller(...) принимает два параметра: индекс в векторе, для которого вы хотите указатель функции, и параметр или данные, которые функция требует в качестве входных данных.

0 голосов
/ 29 декабря 2018

fptr объявлено const, поэтому определите его также const.Кроме того, поскольку Sort является шаблоном, вам нужно typename, чтобы сослаться на MyClass<T>::fptr.

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

Примечание: вы не сможете поместить это определение или определения вашего статическогофункции в исходном файле, поскольку они являются шаблонами.

Демо

Кроме того, рассмотрите возможность использования 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 };

Демо

Есть ли лучший способ сделать это?

Возможно, но я могуне говорите без подробностей о том, что именно вы хотите сделать.

...