我可以有一个模板函数指针的 std::vector 吗?

2024-02-08

我有一个模板函数,我想将它的指针存储在std::vector.

该函数如下所示:

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

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

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

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

EDIT:首先,感谢您的快速回复。这是我在 Stack Overflow 上的第一个问题,所以很抱歉没有提供足够的信息。

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

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

for 循环的迭代次数与向量内的函数指针一样多。每次迭代时,都会使用一些先前默认构造的 T 和一些其他参数来调用该函数。最后的目标是拥有 8 个带有特定于该功能的数据的启动 T。

EDIT2:如果有帮助,这里是一些实际的源代码。在以下函数模板中,我想访问函数指针向量以调用相应的函数。

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();
            }
        }
    }
}

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

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

模板是一种先进的技术静态多态性 http://www.cpptutor.com/static-polymorphism-and-dynamic-polymorphism-in-c++.htm。在类型化语言(如 C++)中,如果没有静态多态性,您将必须单独定义使用的每个实体并精确指示引用的每个实体。

C++ 中的静态多态性机制允许自动指示函数或方法,并将其推迟到通过构建超载。它允许您通过以下方式同时定义共享某些特征的多个实体模板并将特定专业的定义推迟到构建(从使用中推断)。

(请注意,在各种场景中,静态多态性允许单独的代码,因此对使用和定义的更改是独立的,这非常有用。)

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

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

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

这个(可以说是无用的)函数模板不带参数并返回int, 任何T用于专门化模板。因此,只要参数定义为,就可以使用指向它的指针int (*f)()。在这种情况下,您可以在一个向量中保留指向任何专业化的指针。

    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>;

可以看出,函数模板的每个特化都具有相同的类型,并且两个指针都适合在同一个容器中。

下一个案例 - 如果函数头依赖于模板参数怎么办?每个专业化都会有不同的签名,即不同的函数类型。指向所有这些的指针将具有不同的类型 - 所以甚至不可能typedef这个指针一次。

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

在这种情况下,函数模板专业化具有不同类型,具体取决于T用于专门化。

    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>;

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

此时值得一提的是,在这种情况下,没有必要单独定义每个指针类型。它们可以是模板类型:

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

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

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

在更复杂的情况下,可以创建一个模板,其每个特化都是不同的类型,然后使用具体向量的单个实例来存储指向仅模板的特化之一类型的函数的各种指针。尽管像示例中这样的简单模板只能为每种类型生成一个函数,但因为每个特化都会生成一种类型的函数和该类型的一个函数,但并非不可能设想一种场景,其中获得了指向函数的各种指针,两者都指向特化和通常的功能,也许来自不同的来源。所以这项技术可能有用。

但另一种情况是,尽管模板的每个专业化都具有不同的类型,但仍然需要将指向各种专业化的指针存储在单个模板中。std::vector。在这种情况下动态多态性会有帮助的。为了存储不同类型的值,fe。在一种类型的变量中,指向不同类型函数的指针需要遗产。可以将任何子类存储在定义为超类的字段中。Note然而,这不太可能真正完成任何事情,而且可能不是您真正想要的。

我现在看到两种普遍的可能性。要么使用带有方法的类模板,该方法继承自非模板类。

    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,所以一个指向 a 的指针BaseClass实际上可以指向它们中的任何一个,并且std::vector<funcPointerBase>可以用来存储它们。通过超载operator()我们创建了一个模仿函数的对象。这种类的有趣属性是它可以具有使用参数构造函数创建的多个实例。因此,类模板有效地生成多种类型的特化,而每个特化类又可以生成不同参数化的实例。

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

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

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

我不是函子方面的专家,只是想介绍一下总体思路。如果它看起来很有趣,我建议现在就研究一下。

但从技术上讲,我们不存储函数指针,只存储常规对象指针。嗯,如前所述,我们需要继承来使用一种类型的变量来存储各种类型的值。因此,如果我们不使用继承来将过程函数交换为动态多态的东西,那么我们必须对指针做同样的事情。

    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>存储所有可能的伪函数指针。

现在是非常重要的一点。在这两种情况下,你会如何称呼它们?因为在这两种情况下它们都存储在单个std::vector<>,它们被视为基本类型。特定的函数调用需要特定类型的参数并返回特定类型。如果所有子类都可以以相同的方式执行任何操作,则可以通过在基类中定义这样的方法来公开它(在任一情况下使用函子或指针..or?),但特定的专用函数调用不是那种类型的东西。经过所有这些斗争之后,您最终想要执行的每个函数调用都将是不同的类型,需要不同类型的参数和/或返回不同类型的值。因此,它们永远不可能都适合通常的同一个地方,而不是模板化的代码,在相同的执行环境下。如果他们这样做了,那么首先就不需要动态多态性来解决这个问题。

可以做的一件事 - 这是非常不鼓励的,并且可能违背动态多态性的目的 - 是在运行时检测子类类型并相应地进行。如果您确信自己有一个很好的使用此功能的案例,请进行研究。但最有可能的是,这可能是一个很大的反模式。

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

我可以有一个模板函数指针的 std::vector 吗? 的相关文章

随机推荐

  • 如何动态更改引导程序模态体

    所以我将 Bootstrap 模态定义为 div class modal fade div class modal dialog modal sm div class modal content div class modal header
  • 如何在Android应用程序中读取和使用网站内容

    我实际上必须在 Android 应用程序中阅读和使用某些网站的内容 到目前为止 我主要使用两种不同的代码来获取网站的内容 但它们对我不起作用 public static String connect String url String re
  • 将 django 默认 pk 与 AutoField 更改为 BigAutoField

    我的模型有一个带有 AutoField 整数 的默认 pk 但后来我发现我需要使用 BigAutoField 然后我还有引用学生模型的其他模型的数据 我如何将 pk 字段更改为 BigAutoField 并反映在其他引用模型上 class
  • 当我尝试使用 vue js 显示 JSON 数据时,Selectpicker 不起作用?

    当我写 selectpicker selectpicker refresh 时在控制台中它正在加载 我应该在哪里提供此代码 我的 HTML 代码是
  • 错误 1045 (28000):用户“root”@“localhost”的访问被拒绝

    所以我第一次安装了MySQL应用程序 首先我看到命令行客户端没有打开 所以我寻找解决方案 他们说我必须进入 bin 目录并手动运行它 在我运行cmd之后mysql uroot p运行它并输入密码 它给了我错误 错误 1045 28000 用
  • 剪刀石头布 - Python 3 - 初学者

    我想模拟一个石头剪刀布游戏 这就是我到目前为止所拥有的 它不允许我在其中输入字母scoregame功能 我怎样才能解决这个问题 def scoregame player1 player2 if player1 R and player2 R
  • 防止选项卡循环浏览地址栏

    我意识到这可能是一个可访问性问题 最好不要管它 但我想弄清楚是否可以阻止选项卡在选项卡循环中访问地址栏 我的应用程序有另一种循环输入区域的方法 但许多新用户本能地尝试使用该选项卡 但它无法按预期工作 这是一个通用的 jquery 实现 您不
  • Selenium Instagram 机器人 - 单击“喜欢”按钮

    我已经编写了一个程序来访问 Instagram 探索页面 并喜欢前六张照片 现在 我正在使用这种相当复杂的方法来查找 喜欢 按钮 我更愿意将其格式化为 单击登录按钮 部分 到目前为止 我已经尝试检查各种元素 但我无法确定正确的元素以使其唯一
  • Chart.js 圆环图大小调整

    我在用着ng2 图表 https github com valor software ng2 charts在 Angular 项目中 我有该项目的两个版本 当前的生产版本是旧版本 并且使用旧版本的 ng2 charts 以及扩展的 Char
  • Rust 中与闭包和生命周期作斗争

    我正在尝试将一些基准测试从 F 移植到 Rust F 代码如下所示 let inline iterNeighbors f i j f i 1 j f i 1 j f i j 1 f i j 1 let rec nthLoop n s1 Ha
  • 休息删除线

    是否可以在重组文本中删除文本 例如呈现为
  • 将自定义控件中的编辑框动态绑定到托管 bean

    我读过许多关于在自定义控件中动态绑定字段的优秀帖子和文章 但它们都假设了文档数据源 我想允许托管 bean 数据源的可能性 我尝试将属性类型设置为com ibm xsp model DataSource or com ibm xsp ext
  • Enunciate 能否为处理泛型类型的 API 生成文档?

    给定一个抽象的通用 Resource 类和一个具体的实现 public abstract class AbstractResource
  • 如何阻止混淆整个包?

    我需要防止 Proguard 混淆包中的任何类com foo 我努力了 keep com foo
  • 如何模拟当前日期?

    我的代码中有一个方法可以验证当天是否正常工作 它会为此检查数据库日历 方法如下所示 public boolean iBusinessDayToday LocalDate today LocalDate now logic with toda
  • 基于属性值的条件(XML 架构)

    是否可以在 XML 模式中定义基于属性值的条件 例如 当test attrib one 我想one element被允许和强制或当test attrib two 我想two element是允许的和强制性的 例如 有效文件是
  • 如何使用控制台生产者在 Kafka 0.11 中生成带有标头的消息?

    如何使用控制台生产者在 Kafka 0 11 中生成带有标头的消息 我在Kafka文档中没有找到任何关于此的描述 Update 从 Kafka 3 2 开始 您可以使用以下命令生成带标题的记录kafka console producer s
  • 将变量从组件传递到模型范围

    我正在使用基于 Laravel 的 OctoberCMS 我正在尝试从 URL 获取标识符并将其传递到范围以过滤数据库结果 this gt property username 起作用并从 URL 返回用户名 但是如何将它传递给模型和范围函数
  • JSON 点符号转字符串

    我在 javascript 中使用 JSON 并且尝试获取点表示法表示的字符串值 例如AAA BBB 0 CCC DDD 5 EEE 123 采用 JSON 点表示法格式 但我想获得价值AAA BBB 0 CCC DDD 5 EEE作为字符
  • 我可以有一个模板函数指针的 std::vector 吗?

    我有一个模板函数 我想将它的指针存储在std vector 该函数如下所示 template