我可以有一个std :: vector模板函数指针吗? [英] Can I have a std::vector of template function pointers?

查看:60
本文介绍了我可以有一个std :: vector模板函数指针吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个模板函数,我想将指针存储在 std :: vector 内部。

I have a template function that I want to store a pointer to inside a std::vector.

该函数如下:

template<typename T> void funcName(T& aT, std::vector<std::string>& fileName){...}

现在,我想在 std :: vector 中存储指向此类函数的多个指针。对于非模板函数,我会这样:

Now I want to store multiple pointers to functions of this kind inside a std::vector. For non-template functions I would do it like this:

typedef std::vector<std::string> string_vt;
typedef void func_t(T&, string_vt&);
typedef func_t* funcPointer;
typedef std::vector<funcPointer> funcPointer_vt;

但是模板函数的正确语法是什么?我如何存储它们?

But what is the correct syntax for template functions? How can I store them?

编辑:首先,感谢您的快速回复。这是我关于堆栈溢出的第一个问题,所以很抱歉没有提供足够的信息。

First of all, thank you for your fast response. This was my first Question on Stack Overflow, so I am sorry for not providing enough information.

T的集合是有限的,它可以是ClassA类型,也可以是type B类。在这些功能模板中,我想使用一些硬编码数据对T(即ClassA或ClassB)进行更改。我有8个这些函数,它们基本上使用该函数专用的数据来初始化默认构造的T。在我的程序中,我要启动2 * 8默认构造的T(8个ClassA和8个ClassB)。因此,我运行了一个for循环,依次调用一个函数,以该函数的主体数据初始化T对象。

The set of T is finite, it can either be of type ClassA or type classB. In these function templates I want to do changes to T (so either ClassA or ClassB) with some hard coded data. I have 8 of these functions, which basically initiate a default constructed T with data specific to the function. In my program, I want to initiate 2*8 default constructed T's (8 ClassA and 8 ClassB). Therefore I run a for loop, calling one function after the other, to initiate my T objects with the function's body data.

for(int i = 0; i < initT.size(); ++i){
   init_T[i]<T>(someT, fileName);
}

for循环的迭代次数与向量中的函数指针相同。在每次迭代中,都会使用一些以前默认构造的T和其他一些参数来调用该函数。最后,目标是要有8个初始化T,其中包含特定于该函数的数据。

The for loop has as much iterations as there are function pointers inside the vector. At every iteration the function is called with some previously default constructed T and some other parameter. At the end the goal is to have 8 initiated T's with data specific to the function.

EDIT2:实际的源代码。在下面的函数模板中,我想访问我的函数指针向量以调用相应的函数。

In case it helps, here is some actual source code. Inside the following function template I want to access my vector of function pointers in order to call the respective function.

template<typename T_Relation, typename T_Relation_Vec, bool row>
void bulk_load(initRelation_vt& aInitFunctions, T_Relation_Vec& aRel_Vec, const bool aMeasure, const uint aRuns, const char* aPath)
{
    for(size_t i = 0; i < aRuns; ++i)
    {
        MemoryManager::freeAll();
        aRel_Vec.clear();
        string_vt fileNames;
        for(size_t j = 0; j < aInitFunctions.size(); ++j)
        {
            aRel_Vec.emplace_back(T_Relation());
            aInitFunctions[j]<T_Relation>(aRel_Vec[j], fileNames);
            BulkLoader bl(fileNames[j].c_str(), tuples, aRel_Vec[j], delimiter, seperator);
            Measure lMeasure;
            if(aMeasure)
            {
                lMeasure.start();
            }
            try
            {   
                bl.bulk_load();
                if(row)
                {
                    BulkInsertSP bi;
                    bi.bulk_insert(bl, aRel_Vec[j]);
                }
                else
                {
                    BulkInsertPAX bi;
                    bi.bulk_insert(bl, aRel_Vec[j]);
                }
            }
            catch(std::exception& ex)
            {
                std::cerr << "ERROR: " << ex.what() << std::endl;
            }
            lMeasure.stop();
            if(aMeasure)
            {
                std::ofstream file;
                file.open (aPath, std::ios::out | std::ios::app);
                //print_result(file, flag, lMeasure.mTotalTime());
                file.close();
            }
        }
    }
}

此行是访问函数模板指针向量的地方。

This line is where the vector of function template pointers is accessed.

aInitFunctions[j]<T_Relation>(aRel_Vec[j], fileNames);


推荐答案

模板是静态多态。在像C ++这样的类型化语言中,如果没有静态多态性,则必须分别定义所使用的每个实体,并精确指示所引用的每个实体。

Templates are an advanced technique for static polymorphism. In a typed language, like C++, without static polymorphism you would have to separately define every entity used and precisely indicate every entity referred to.

C ++中的静态多态性机制允许自动指示功能或方法,并将其推迟到通过重载构建。它允许您通过模板一次定义多个共享某些特征的实体,并将特定专业的定义推迟到生成为止(从使用推断)。

Mechanisms of static polymorphism in C++ allow to automate indication of function or method and defer it until build via overloading. It allows you to define multiple entities sharing some characteristics at once via templates and defer definition of particular specializations until build, inferred from use.

请注意,在各种情况下,静态多态性允许使用单独的代码,因此使用和定义的更改是独立的,这非常有用。

此机制的重要含义是模板的每个专业化类型可能不同。截至我回复时还不清楚,是否要在一种类型的容器中存储指向一种或多种专业化类型的指针。可能性还取决于函数模板的参数和结果类型。

The important implication of this mechanism is that every specialization of your template may be of different type. It is unclear, as of when I'm responding, whether you want to store pointers to a single or multiple types of specialization in one type of container. The possibilities depend also on parameter and result types of the function template.

C ++中的函数的类型是其参数类型列表及其返回类型的组合。换句话说,接受和返回相同类型的两个函数是同一类型。如果您的函数模板既没有采用也不返回模板参数类型(即 T )或模板化类型(例如 std :: vector< T> ),则此函数模板的每个特殊化都将采用并返回相同的类型,因此将是相同类型的函数。

A function in C++ has a type that is a combination of list of its parameter types and its return type. In other words, two functions that take and return the same types are of the same type. If your function template neither took or returned template parameter type (ie. T) nor templated type (eg. std::vector<T>), every specialization of this function template would be taking and returning the same types and would therefore be a function of the same type.

    template <typename T>
    int func() { ... }

这个(可能毫无用处的)功能模板需要没有参数并返回 int ,无论使用什么 T 来专门化模板。因此,只要参数定义为 int(* f)(),都可以使用指向它的指针。在这种情况下,您可以保持指向一个向量中任何专业化的指针。

This (arguably useless) function template takes no arguments and returns int, whatever T is used to specialize the template. Therefore a pointer to it could be used wherever the parameter is defined as int (*f)(). In this case you could keep pointer to any specialization in one vector.

    typedef std::vector<std::string> string_vt;
    typedef int func_t();
    typedef func_t* funcPointer;
    typedef std::vector<funcPointer> funcPointer_vt;

    funcPointer x = &func<int>;
    funcPointer y = &func<float>;

可以看出,函数模板的每个特殊化都是相同的类型,并且两个指针都适合

As can be seen, every specialization of your function template is of the same type and both pointers fit in the same container.

下一种情况-如果函数头取决于模板参数怎么办?每个专业化将具有不同的签名,即不同的功能类型。指向所有这些指针的指针将具有不同的类型-因此甚至不可能一次 typedef 该指针。

Next case - what if function header depends on a template parameter? Every specialization would have a different signature, that is a different function type. The pointers to all of them would be of different types - so it wouldn't be possible to even typedef this pointer once.

    template <typename T>
    void func(std::vector<T> param) { ... }

在这种情况下,函数模板的专业化类型取决于用于专门化的 T 的类型。

In this case function template specialization is of different type depending on T used to specialize.

    typedef int func_t_int(std::vector<int>);
    typedef func_t_int* funcPointerInt;
    typedef std::vector<funcPointerInt> funcPointerInt_vt;

    typedef float func_t_float(std::vector<float>);
    typedef func_t_float* funcPointerFloat;
    typedef std::vector<funcPointerFloat> funcPointerFloat_vt;

    funcPointerInt x = &func<int>;

    funcPointerFloat x = &func<float>;

专业化类型不同,因为它们采用不同类型的向量。指针不能放在同一个容器中。

Specializations are of different types, because they take different type of vectors. Pointers do not fit in the same container.

在这一点上值得一提的是,在这种情况下,不必分别定义每种指针类型。它们可以是模板类型:

It's mention-worthy at this point, that in this case it's not necessary to define every pointer type separately. They could be a template type:

    template <typename T>
    using funcPointer = void (*)(std::vector<T>);

现在允许 funcPointer< int> 用作类型限定符,代替之前的 funcPointerInt

Which now allows funcPointer<int> to be used as a type qualifier, in place of earlier funcPointerInt.

    funcPointer<float> y = &func<float>;

在更复杂的情况下,可以创建一个模板,其每个专业化类型都不同,然后将使用具体向量的单个实例来存储指向模板的一种特殊化类型的函数的各种指针。尽管像示例中那样的简单模板只能为每种类型生成一个函数,但是由于每种专业化都会产生一种类型的函数,并且会产生该类型的一种函数,因此并非不可能设想出一种获得各种指向函数的指针的情况和通常的功能,可能来自各种来源。

In more complicated situations a template could be created, whose every specialization is of a different type, and then would use a single instance of concrete vector to store various pointers to functions of type of only one of the specializations of your template. Although a simple template like in the example can only produce a single function per type, because every specialization yields one type of function and one function of that type, it's not impossible to conceive a scenario where various pointers to functions are obtained, both to specializations and usual functions, perhaps from various sources. So the technique could be useful.

但是还有另一种情况是,尽管模板的每个专业化类型都是不同的,但仍需要将指向各种专业化的指针存储在单个模板中 std :: vector 。在这种情况下,动态多态性会有所帮助。为了存储不同类型的值,fe。在一种类型的变量中,指向不同类型函数的指针需要继承力。可以将任何子类存储在定义为超类的字段中。 请注意,但是,这不可能真正完成任何事情,也可能无法完成您真正要寻找的事情。

But yet another scenario is that despite every specialization of the template being of different type, there's a need to store pointers to various specializations in single std::vector. In this case dynamic polymorphism will be helpful. To store values of different types, fe. pointers to functions of different types, in one type of variable, requires inheritance. It is possible to store any subclass in a field defined as superclass. Note however, that this is unlikely to accomplish anything really and probably not what you're really looking for.

我现在看到两种普遍的可能性。

I see two general possibilities now. Either use a class template with a method, which inherits from a non-template class.

    template <typename T>
    class MyClass : BaseClass
    {
    public:
        T operator()(const T& param, int value);
    }

    MyClass<int> a;
    MyClass<float> b;
    BaseClass* ptr = &a;
    ptr = &b;

虽然此类的每个专业化类别可能不同,但是它们都共享超类 BaseClass ,因此指向 BaseClass 的指针实际上可以指向其中任何一个,而 std :: vector< ; funcPointerBase> 可用于存储它们。通过重载 operator(),我们创建了一个模仿函数的对象。此类的有趣特性是它可以具有使用参数构造函数创建的多个实例。因此,有效的类模板可以产生多种类型的特殊化,而每个特殊类又可以产生变化的参数化实例。

While every specialization of this class may be of a different type, they all share superclass BaseClass, so a pointer to a BaseClass can actually point to any of them, and a std::vector<funcPointerBase> can be used to store them. By overloading operator() we have create an object that mimics a function. The interesting property of such a class is that it can have multiple instances created with parameter constructors. So effectively class template produces specializations of multiple types, and in turn every specialized class can produce instances of varying parametrization.

    template <typename T>
    class MyClass : BaseClass
    {
        int functor_param;
    public:
        MyClass(int functor_param);
        T operator()(const T& param, int value);
    }  

此版本允许创建工作方式不同的实例:

This version allows creation of instances that work differently:

    MyClass<int> a(1);
    MyClass<int> b(2);
    MyClass<float> c(4);
    MyClass<int>* ptr = &a;
    ptr = &b;
    ptr = &c;

我不是函子的专家,只是想提出一个一般的想法。如果看起来有趣,建议立即进行研究。

I am no expert on functors, just wanted to present the general idea. If it seems interesting, I suggest researching it now.

但是从技术上讲,我们不存储函数指针,而只是存储常规对象指针。嗯,正如前面所述,我们需要继承来使用一种类型的变量来存储各种类型的值。因此,如果我们不使用继承将过程函数交换为动态多态的东西,则必须对指针执行相同的操作。

But technically we're not storing function pointers, just regular object pointers. Well, as stated before, we need inheritance to use one type of variable to store values of various types. So if we're not using inheritance to exchange our procedural functions for something dynamically polymorphic, we must do the same to pointers.

    template <typename T>
    T func(std::pair < T, char>) {}

    template <typename T>
    using funcPointer = T(*)(std::pair<T, char>);

    template <typename T>
    class MyPointer : BasePointer
    {
        funcPointer<T> ptr;

    public:
        MyPointer(funcPointer<T> ptr);
        T()(std::pair <T, char>) operator*(std::pair <T, char> pair)
        {
            *ptr(pair);
        }
    };

这又允许创建单个 std :: vector< BasePointer> 来存储所有可能的伪函数指针。

This, again, allows creation of single std::vector<BasePointer> to store all possible pseudo-function-pointers.

现在非常重要。在任何一种情况下,您将如何打电话给这些人?由于在两种情况下它们都存储在单个 std :: vector<> 中,因此将它们视为基本类型。特定的函数调用需要特定类型的参数并返回特定类型。如果所有子类都可以以相同的方式进行操作,则可以通过在基类中定义这样的方法来公开它(在使用函子或指针..or的情况下),但是特定的专用函数调用不是那种的东西。经过所有这些努力之后,您最终希望执行的每个函数调用都将具有不同的类型,需要不同的参数类型和/或返回不同的值类型。因此,它们永远都不可能在通常的,没有模板的代码,执行的相同情况下都适合放在同一位置。如果他们这样做了,那么动态多态就不必首先解决这个问题。

Now the very important bit. How would You go about calling those, in either scenario? Since in both cases they are stored in a single std::vector<>, they are treated as if they were of the base type. A specific function call needs parameters of specific type and returns a specific type. If there was anything that all subclasses can do in the same way, it could be exposed by defining such a method in base class (in either scenario using functors or pointer..ors?), but a specific specialized function call is not that kind of thing. Every function call that You would want to perform in the end, after all this struggle, would be of a different type, requiring different type of parameters and/or returning different type of value. So they could never all fit into the same place in usual, not templated code, the same circumstances in execution. If they did, then dynamic polymorphism wouldn't be necessary to solve this problem in the first place.

可以做的一件事-灰心丧气,很可能失败动态多态的目的-是在运行时检测子类类型并相应地进行。研究表明,如果您确信自己有很好的理由使用它。

One thing that could be done - which is greatly discouraged and probably defeats the purpose of dynamic polymorphism - is to detect subclass type at runtime and proceed accordingly. Research that, if you're convinced you have a good case for using this. Most likely though, it's probably a big anti-pattern.

但是从技术上讲,您可能想做的任何事情都是有可能的。

But technically, anything you may want to do is possible somehow.

这篇关于我可以有一个std :: vector模板函数指针吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆