如何为成员函数创建类似模板的命名空间

how to create templated-like namespace for member functions

提问人:Qant123 提问时间:1/7/2022 更新时间:1/7/2022 访问量:103

问:

我目前正在尝试定义一个命名空间/结构,其中包含存储特定实现的函数指针(假设包含多个函数的结构)。目前,以下结构一切正常:

class foo{
    int a;
    int b;

public:
    explicit foo(int _a, int _b) : a(_a), b(_b) {};
    std::function<int(int)> bar(int num) = [=](int num) -> int{
         // here I need to know a and b
         //do something with num and return 
    }
}

此类包含多个函数,每个函数都必须知道 a 和 b。问题是我必须创建类的实例并设置参数 a 和 b,我宁愿省略它们。 在另一个类中,我只通过获取其函数来使用该类。即

class foo2{
    //some other parameters
    int a, b;
    std::function<...> fun1, fun2,...;
public:
    foo2(int a, int b, ....){this->a = a; this->b = b;};
    setFuncs(){
        foo instance(a, b); 
        this->fun1 = [instance](int num){ return instance.bar(num);}
        this->fun2 = ...
    }
}

但我想省略每次都创建一个新的类 inctance(从某种意义上说,我在同一类中重复上述行为,但在代码中的另一个位置)。我试图将这个类模板化为

template<int a, int b>
class foo{
...
}

因此,我可以将功能分配为:

this->fun1 = foo<a,b>::bar;

但是我需要在编译时知道 a 和 b,这是不可能的。这些参数在类 foo2 中设置一次。正如你所看到的,我意识到整体代码可能并不干净,我是一名物理学家,而不是 IT 人员。一种方法是将 foo 类的实例存储在类 foo2 中,并为整个类初始化一次,并让函数 fun1、fun2 ,...可以通过引用这些指针进行访问,但我正在寻找是否有另一种方法(也许是像类这样的模板,我不需要在编译时知道值)。 此外,我无法在此处粘贴整个代码,因为它在多个文件中包含数千行,并且描述代码的作用非常困难。如果这可能是一个愚蠢或微不足道的问题,我很感激任何帮助,并表示歉意(我不严格地在 IT 部门工作,我是一名物理学家;))

C++ 函数 模板 命名空间

评论

1赞 Xeverous 1/7/2022
我想你可能有一个XY问题。我觉得你想要某种预制的函数参数化,但我不明白你的意图。您需要提供某些功能但具有比单个函数调用更大的范围的预定义输入的对象。您可能会错过某个设计模式,或者可能只是将 (XY) 问题过于复杂化。
0赞 Xeverous 1/7/2022
“问题是我必须创建类的实例并设置参数 a 和 b,我宁愿省略它们”——如果您希望任何状态保持的时间超过单个函数调用,这是不可避免的。你希望某些东西保持/应用更长时间,所以(除非它是编译时数据)状态是不可避免的。所有解决方案都将只是数据的封装方式不同 - 结构的成员,捕获 lambda,带有状态。std::function

答:

0赞 Some programmer dude 1/7/2022 #1

您可以在构造函数中创建 lambda,其中 和 的值是已知的。fooab

然后,您还可以捕获以使用成员变量(以防它们在 lambda 创建和调用之间更改)。this

class foo
{
    int a;
    int b;

public:
    // No need for explicit since this isn't a "conversion" constructor
    foo(int a, int b) : a(a), b(b)
    {
        bar = [this](int x)
        {
            // Use the argument together with this->a and this->b...
            return some_value;
        };
    }

    std::function<int(int)> bar;
};

评论

0赞 Qant123 1/8/2022
在构造函数中声明功能栏与在构造函数调用之外将其设置为常量有什么区别?有什么理由可以做得更好吗?通过创建实例,其他类成员(如 bar)使用设置参数 a,b 进行设置,该参数对于此特定实例不会更改
0赞 Some programmer dude 1/8/2022
@Qant123 在任何成员函数(包括构造函数)之外,都无法访问 .如果没有对象,则无法访问任何(非静态)成员变量。this
0赞 Qant123 1/8/2022
明白了。现在我很困惑我的方法是如何工作的。通过在 lambda 中 have = 捕获在构造函数之外声明的函数,仍然是新的非静态数据 memebrs。但尽管如此,这种方法还是容易出错,谢谢!
1赞 Xeverous 1/7/2022 #2

由于您希望某些输入数据比单个函数调用保留更长的时间,因此除非它是完全编译时的数据,否则运行时状态是不可避免的。问题是你希望如何封装这些数据 - 不同的方法会产生非常不同的(主观)感觉,即它们的便利性。

根据您的使用示例:

this->fun1 = foo<a,b>::bar;

如果你想避免状态(或者更确切地说是封装它),你可以创建一个工厂,为你创建函数:

std::function<int(int)> make_func(int a, int b)
{
    return [=](int x){ return actual_function(a, b, x); };
}

this->fun1 = make_func(a, b); // now std::function will hold lambda's captured state

这个主题通常被称为部分应用程序,我猜 boost 或其他库已经有很多支持此类操作的代码。

评论

0赞 Qant123 1/8/2022
这其实是一个非常有趣的IDE,谢谢!我可能会用它!我目前正在考虑如何实现这个想法,因为我在 foo 类中有大约 10 个函数。一方面,我可以创建这样的构造,并在切换大小写声明中通过枚举选择适当的函数并替换整个类,另一方面,我可以保留该类并分别为每个函数创建一个工厂。两种方式都应该有效,有理由选择一种而不是另一种吗?
0赞 Xeverous 1/9/2022
我不明白你的问题。foo 类中有 10 个函数 - 但为什么呢?它们是否共享任何内容(例如,变量)。为什么需要枚举来选择实现?你为什么不立即调用具体的实现?ab
0赞 Qant123 1/12/2022
对不起,回复晚了。是的,它们都共享 a、b,我想省略将它们作为变量传递给函数。一般来说,我指的是一段代码:
0赞 Qant123 1/12/2022
pastebin.com/kq4tksKd代码很长,一般来说,我的问题是指创建类__builtins的实例,如类运算符的构造函数之一所示。几个不同的类使用枚举创建运算符类型的对象,然后选择适当的函数,这就是为什么我想省略创建运行时状态的原因。编辑:这里的a,b表示为“L”和“config”
0赞 Xeverous 1/14/2022
某些状态是不可避免的,并且也有一些内部状态(如果您知道它是如何实现的)。我大致知道你想要什么,但是 1) 我仍然怀疑你希望它如何抽象 2) 如果你发布一个 MCVE 来改进或修改一个未完成的 MCVE(有一些代码空白需要填补),对我来说会容易得多。您发布的粘贴不会编译,并且可能会显着减少。std::function