Определите, является ли параметр функции функцией - PullRequest
0 голосов
/ 30 июня 2018

Как определить, является ли параметр функции тип функцией ? Я реализую класс с именем Queue, который получает один параметр. Если параметр является функцией, он сохраняет функцию.

Вот код:

template <class Type, typename Data>
class Queue {
    public:
        void Enqueue (Data& data) {
            if (typeid(data).name() == int) {
                intVector.push_back(data);
                order.push_back("int");
            }
            else if (typeid(data).name() == bool) {
                boolVector.push_back(data);
                order.push_back("bool");
            }
            else if (typeid().name() == string) {  
              stringVector.push_back(data);
              order.push_back("string");
            }
            // This will continue for:
            // - double
            // - char
            // - function
        }

        auto Dequeue () {
            auto temp;
            switch (order.begin()) {
                case "int":
                    temp = intVector.begin();
                    intVector.erase(intVector.begin());
                    order.erase(order.begin());
                    return temp;
                // This will continue for:
                // - "string"
                // - "bool"
                // - "char"
                // - "double"
                // - "function"
                default:
                    cout << "An Error occurred while trying to Enqueue." << endl;
                    cout << "\tAddress: " << this << endl;
            }
        }

        auto Start () {
            // This function will run all of the processes...
        }
        Queue (Data& data) {
            if (typeid(Type).name() == int) {
                // Pseodo-code:
                // if (data.type == function) {
                //     Enqueue (data);
                // }
            }
        }
}

Может быть инициализирован:

Queue queue1 = new Queue <int> (func ()); // func () is a function.
Queue queue2 = new Queue <int> (var);     // var is a variable.

Ответы [ 4 ]

0 голосов
/ 30 июня 2018

И, так как я потратил время, чтобы немного его изучить (в основном потому, что хотел немного узнать об этом), вот немного сверхпростого SFINAE, сложенного вместе из мудрых .

#include <type_traits>
#include <iostream>

// Primary template (required)
template <class T, class Enable = void>
struct X { };

// Specialisation to take a function pointer
template <class T>
struct X <T, typename std::enable_if <std::is_function<T>::value>::type>
{
    X (T func)
    {
        std::cout << "T is a function\n";
        func ();
    }
};

// Partial specialisation for anything else
template<class T>
struct X <T, typename std::enable_if <!std::is_function<T>::value>::type>
{
    X (T x)
    {
        std::cout << "T is not a function (and x is " << x << ")\n";
    }
};

void foo () { std::cout << "foo () called\n"; }

int main ()
{
    X <void ()> x1 (foo);
    X <int> x2 (42);
}

Выход:

T is a function
foo () called
T is not a function (and x is 42)

Живая демоверсия .

Мощные вещи, но не решение каждой маленькой проблемы.

0 голосов
/ 30 июня 2018

Для примера SFINAE:

Queue(std::enable_if_t<std::is_function_v<Data>, Data>::type & data)
{
    //data is a function
}

//I'm not sure if the enable_if is needed here, maybe you can just do Data& data
Queue(std::enable_if_t<!std::is_function_v<Data>, Data>::type & data)
{
    //data is not a function
}

(для использования std::is_function_v необходимо указать <type_traits>)

0 голосов
/ 30 июня 2018

О боже. Это проблема XY .

Во всяком случае, немного поиграв с std::enable_if (что было довольно забавно), я понял, что все это можно свести к следующему:

#include <vector>
#include <string>
#include <any>
#include <iostream>
#include <functional>

void call_if_function (void (* f) ()) { f (); }
void call_if_function (std::function <void ()> f) { f (); }
void call_if_function (std::any x) { (void) x; }

template <class T>
class Queue
{
    public:
        void Enqueue (const T& data)
        {
//          std::cout << "Enqueueing " << data << "\n";
            v.push_back (data);
        }

        T Dequeue ()
        {
            T ret = v.front ();
//          std::cout << "Dequeueing " << ret << "\n";
            v.erase (v.begin ());
            call_if_function (ret);
            return ret;
        }

    private:
        std::vector <T> v;
};

И, если я правильно понимаю проблему ОП, это все, что вам нужно.

Тестовая программа:

void foo () { std::cout << "foo () called\n"; }
void bar (int x, int y) { std::cout << "bar () called, x = " << x << ", y = " << y << "\n"; }

int main ()
{
    // Queue of int's
    Queue <int> int_q;
    int_q.Enqueue (42);
    auto i = int_q.Dequeue ();
    std::cout << "int_q.Dequeue () returned " << i << "\n\n";

    // Queue of strings
    Queue <std::string> string_q;
    string_q.Enqueue ("Hello world");
    auto s = string_q.Dequeue ();
    std::cout << "string_q.Dequeue () returned " << s << "\n\n";

    // Call function with no parameters    
    Queue <void (*)()> func_q;
    func_q.Enqueue (foo);
    auto f = func_q.Dequeue ();
    std::cout << "func_q.Dequeue () returned " << (void *) f << "\n";
    f ();

    // Call function with arbitrary parameters
    Queue <std::function <void ()>> func_qp;
    func_qp.Enqueue ([] () { bar (21, 99); });
    auto fp = func_qp.Dequeue ();
    fp ();
}

Выход:

int_q.Dequeue () returned 42

string_q.Dequeue () returned Hello world

foo () called
func_q.Dequeue () returned 0x4026fd
foo () called

bar () called, x = 21, y = 99
bar () called, x = 21, y = 99

Живая демоверсия .

Мораль: ПОЦЕЛУЙ, в коробке с игрушками сейчас слишком много игрушек. Наслаждайтесь выходными людьми.

0 голосов
/ 30 июня 2018

Как определить, является ли тип параметра функции функцией?

Вы можете использовать std::is_function для этого.

Реализация, подобная

template <class Type, typename Data>
class Queue {
    public:
        Queue (Data& data) {
            if (typeid(Type).name() == int) {
                // Pseodo-code:
                if (std::is_function<data.type>::value) {
                     Enqueue (data);
                }
            }
        }
}

не будет работать, хотя часть внутри области блока if видна компилятором для других типов данных.

Чтобы понять, что вам нужно использовать SFINAE , и предоставить различные специализации функции конструктора Queue, используя std::enable_if.

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