确定函数参数是否为函数

时间:2018-06-30 06:35:58

标签: c++ templates

如何确定函数的参数 type 是否为函数?我正在实现一个名为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 :(得分:2)

哦,天哪。这有点XY problem

无论如何,在与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;
};

而且,如果我正确理解OP的问题,那就是您所需要的全部。

测试程序:

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

Live demo

道德:亲吻,这几天玩具箱里的玩具太多了。享受周末的人。

答案 1 :(得分:2)

而且,由于我花了一些时间来研究它(主要是因为我想学习一些有关它的知识),所以这里有一些来自the wise ones的非常简单的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)

Live demo

功能强大,但不能解决所有小问题。

答案 2 :(得分:1)

  

如何确定函数的参数类型是否为函数?

您可以使用std::is_function来做到这一点。

类似于

的实现
frame_data = pd.read_csv('final results.csv', header=[0,1])
frame_data[('exp', 'Mean')] = frame_data.iloc[:, -3:].mean(axis=1)

#flatten MultiIndex to columns 
frame_data.columns = frame_data.columns.map('_'.join)

grouped_by_group = frame_data.groupby('8_Group')['exp_Mean'].mean()
print (grouped_by_group)
8_Group
0.1     72.150000
1       92.433333
HD 0    88.966667
WT 0    71.519048
Name: value, dtype: float64

grouped_by_group.plot.bar(title='Grip')

但是不起作用,因为编译器会看到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); } } } } 块作用域内的其他数据类型。

要意识到您将需要使用SFINAE,并使用std::enable_ifif构造函数提供不同的专业化。

答案 3 :(得分:-1)

对于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
}

(您需要包括<type_traits>才能使用std::is_function_v