简体   繁体   English

适用于仅限标头库中的静态成员变量的setter和getter

[英]Proper setter and getter for static member variable in header-only library

I have a few small header-only libraries (the header-only part is important). 我有一些小的头文件库(仅头部部分很重要)。 In the initial versions, I had some static members in the classes defined therein. 在初始版本中,我在其中定义的类中有一些静态成员。 It didn't occur to me until later (when I used them in a bigger project) that the static members would violate the ODR. 直到后来(当我在一个更大的项目中使用它们时)我才发现静态成员会违反ODR。 I wanted to keep them header-only, so defining the static members in a separate .cpp file was out of the question. 我想让它们只保留头文件,因此在一个单独的.cpp文件中定义静态成员是不可能的。 One well-known solution is to use a Meyers singleton function-local static variable for each static member (as suggested, for example, here ). 一个众所周知的解决方案是为每个静态成员使用Meyers单例函数 - 局部静态变量(例如,如此处所示 )。

That is all well and good, but since I want the singleton to behave like a member variable , I want to be able to get and set the value using setters and getters. 这一切都很好,但由于我希望单例表现得像一个成员变量 ,我希望能够使用setter和getter来获取和设置值。 But what do getters and setters for Meyers singletons function-local static variables look like? 但是Meyers单例功能的局部静态变量看起来像是什么? I haven't been able to find any solutions to that particular problem. 我无法找到任何特定问题的解决方案。

To clarify, these are the requirements: 澄清一下,这些是要求:

  • I want the behaviour of a static member variable inside a header-only library (so I cannot put definitions in a .cpp file) 我希望静态成员变量的行为在一个只有头的库中(所以我不能把定义放在.cpp文件中)
  • I want a getter which is a getter only (I shouldn't be able to modify the value by assigning to the reference returned by the getter) 我想要一个只有 getter的getter (我不能通过赋值给getter返回的引用来修改它)
  • I also want to be able to modify the value via a dedicated setter . 我还希望能够通过专用的setter修改该值。

EDIT 1: 编辑1:

I would like to explain why you might need this. 我想解释一下为什么你可能需要这个。

The static variables in the libraries I mentioned define the default values for some parameters. 我提到的库中的静态变量定义了一些参数的默认值。 However, rather than hard-coding these default, I want to give the user the option to set the default values at the beginning of the program so they don't have to pass the values manually each time they call a member function or construct a new instance. 但是,我想让用户在程序开头设置默认值,而不是硬编码这些默认值,这样他们就不必在每次调用成员函数或构造一个函数时手动传递值。新实例。

Also, although I agree that the use of the term "Meyers singleton" in the example provided here is misleading (I'm just using an int value), there is nothing stopping you from using this paradigm with custom classes which you only want a single instance of. 此外,虽然我同意在这里提供的示例中使用术语“Meyers singleton”具有误导性(我只是使用int值),但是没有什么能阻止您使用这个范例,而您只需要一个自定义类单个实例。 In such cases, the "Meyers singleton" term would be justified. 在这种情况下,“Meyers singleton”一词是合理的。


EDIT 2: 编辑2:

This has become somewhat irrelevant with the introduction of inline static variables in C++17, but I'll leave it up for people who don't have the option to use C++17. 这与在C ++ 17中引入inline static变量有些无关,但我会把它留给那些没有选择使用C ++ 17的人。

Solution

#include <iostream>

class Foo
{

    private:

        static int& val()
        {
            static int v = 0;
            return v;
        }

    public:

        Foo()
        {
            set_val(14);
        }

        Foo(const int _v)
        {
            set_val(_v);
        }

        // The setter uses the fact that val()
        // returns a non-const reference,
        // so we can assign to it.
        static void set_val(const int _v)
        {
            val() = _v;
        }           

        // A true getter.
        // Returns const int&, so we cannot assign to it.
        static const int& get_val()
        {
            return val();
        }
};

int main(void)
{

    std::cout << "val is " << Foo::get_val() << "\n";
    Foo f1; // Set the value implicitly via an object constructor
    std::cout << "val is " << Foo::get_val() << "\n";
    Foo f2(5); // Set the value explicitly via an object constructor
    std::cout << "val is " << Foo::get_val() << "\n";
    Foo::set_val(42);
    std::cout << "val is " << Foo::get_val() << "\n";
    // Foo::get_val() = 4; // Doesn't compile, as required

    return 0;
}

Output: 输出:

val is 0
val is 14
val is 5
val is 42

Setting the value via constructors can (and probably should) be omitted. 通过构造函数设置值可以(也可能应该)省略。 I just wanted to show that it can be done. 我只想表明它可以做到。 This is a lot of code just for one variable, but not that much more than for a non-static member. 这是一个很大的代码只是一个变量,而不是一个非静态成员并不多

Any thoughts, comments and suggestions welcome! 欢迎任何想法,意见和建议!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM