我可以有一个模板函数指针的 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 吗? 的相关文章

  • 在 LINQ 查询中进行转换

    是否可以在 LINQ 查询中进行强制转换 为了编译器的缘故 下面的代码并不糟糕 但最好将其放入一个查询中 Content content dataStore RootControl as Controls Content List
  • 非模板函数中的尾随返回类型[重复]

    这个问题在这里已经有答案了 我见过有人使用以下语法来实现函数 auto get next gt int 代替 int get next 我理解两者 并且我知道尾随返回类型语法对于使用 decltype 的模板代码很有用 就我个人而言 我会避
  • 使用 POST 的 HttpWebRequest 的性能

    我有一个用于测试网络服务的小工具 它可以使用 POST 或 GET 调用 Web 服务 使用POST的代码是 public void PerformRequest WebRequest webRequest WebRequest Creat
  • 获取列表框中视图中的项目

    我有一个 ListBox 其属性 VirtualizingStackPanel VirtualizationMode 设置为 回收 我正在绑定一个自定义集合 实现IList and IList
  • 用于 C++ 中图像分析的 OpenCV 二进制图像掩模

    我正在尝试分析一些图像 这些图像的外部周围有很多噪声 但内部有一个清晰的圆形中心 中心是我感兴趣的部分 但外部噪声正在影响我对图像的二进制阈值处理 为了忽略噪音 我尝试设置一个已知中心位置和半径的圆形蒙版 从而使该圆之外的所有像素都更改为黑
  • 注入包含接口的所有已注册实现的 Enumerable

    给出以下接口 public interface IMyProcessor void Process 我希望能够注册多个实现 并让我的 DI 容器将它们的可枚举注入到这样的类中 public class MyProcessorLibrary
  • 使用 STL 流时如何格式化我自己的对象?

    我想将我自己的对象输出到 STL 流 但具有自定义格式 我想出了这样的东西 但由于我之前从未使用过 locale 和 imbue 所以我不知道这是否有意义以及如何实现 MyFacet 和operator 所以我的问题是 这是否有意义以及如何
  • 更改私有模块片段是否会导致模块重新编译?

    On 此页面有关 C 20 模块功能 https www modernescpp com index php c 20 modules private module fragment and header units 我发现了这样的说法 借
  • MINIX内部碎片2

    我正在用 C 语言编写一些软件 它递归地列出给定目录中的所有文件 现在我需要计算出内部碎片 我花了很长时间研究这个问题 发现 ext2 上的内部碎片只发生在最后一个块中 我知道理论上你应该能够从索引节点号获得第一个和最后一个块地址 但我不知
  • fgets溢出后如何清除输入缓冲区?

    当输入字符串超出其预定义限制时 我遇到了 fgets 的小问题 以下面的例子为例 for index 0 index lt max index printf Enter the d string index 1 if fgets input
  • 如何在VS2005中使用从.bat而不是.exe启动的外部程序进行调试?

    在我的 c 项目的调试属性中 我选择了 启动外部程序 并选择了我希望将调试器附加到的程序的 exe 但是 现在我需要从 bat 文件而不是 exe 启动程序 但 VS2005 似乎不允许这样做 这可能吗 编辑 为了澄清 我需要调试从 bat
  • 在一个解决方案中调用不同项目的方法

    1 个解决方案中有 3 个项目 我对第一个项目中的主文件进行的主要操作 但是我需要调用第三个项目中的方法并使用类 例如 第三个项目有 public DataClasses1DataContext base global WindowsFor
  • g++ / gcc 是否支持 C++20 新的atomic_flag 功能?

    根据参考参数 https en cppreference com w cpp atomic atomic flag c 20 有丰富的 对我来说有用的 支持atomic flag运营 然而 目前尚不清楚 gcc 是否支持这些功能 它们在任何
  • 使用未命名命名空间而不是静态命名空间

    我可以假设在未命名命名空间中声明的对象相当于static namespace int x 1 static int x 2 FWIK 在这两种情况下 x将具有静态存储期限和内部链接 声明为的对象的所有规则也是如此static适用于未命名名称
  • 查找数组中的多个索引

    假设我有一个像这样的数组 string fruits watermelon apple apple kiwi pear banana 是否有一个内置函数可以让我查询 apple 的所有索引 例如 fruits FindAllIndex ap
  • C# 多维数组解析

    我有一个多维数组 内容在调试器中看起来像这样 数组设置为 String s new String 6 4 A B Yes C A B Yes C A B No C A B Yes C A B Yes C A B Yes C A B No C
  • 在多线程环境中捕获信号

    我有一个大型程序 需要尽可能具有弹性 并且有大量线程 我需要捕获所有信号SIGBUS SIGSEGV 并在必要时重新初始化有问题的线程 或者禁用该线程以继续减少功能 我的第一个想法是做一个setjump 然后设置信号处理程序 可以记录问题
  • C++ 中的析构函数

    我的 AB h 文件中有一个构造函数 class AB private int i public AB i 0 constructor AB i 0 destructor virtual void methodA unsigned int
  • 如何配置 qt Creator 以显示 C++ 代码而不是反汇编程序?

    昨天我做了很多事情 比如更新 GCC Clang 和重新安装 Qt Creator 今天 在逐步调试我的代码时 调试器显示的是反汇编代码 而不是我编写的 C 代码 紧迫F10 or F11 调试器正在进入汇编代码而不是 cpp nor h我
  • java有类似C#的属性吗? [复制]

    这个问题在这里已经有答案了 C 属性 我的意思是 get 和 set 方法 是一个非常有用的功能 java 也有类似 C 的属性吗 我的意思是我们如何在 java 中实现类似以下 C 代码的内容 public string Name get

随机推荐

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

    所以我将 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