使用静态const结构对相关的类常量进行分组(C ++ 11)

时间:2018-07-03 21:04:20

标签: c++ c++11

使用以下(A)的(缺点)有哪些:

// .h
class SomeClass
{
    static const struct ConstantGroup
    {
        int a = 1;
        string b = "b";
        // ... etc.
    } CONSTANT;
};
// .cpp
const SomeClass::ConstantGroup SomeClass::CONSTANT;

对(B):

// .h
class SomeClass
{
    static const int A;
    static const string B;
    // .. etc.
};
// .cpp
const int SomeClass::A = 1;
const string SomeClass::B = "b";

...对于某些组相关的静态类常量?假设不涉及模板,并且常量包含简单类型(POD或字符串)。

到目前为止,我看到以下有利于(A)的优点:

  • 相关常量可以作为一个组传递。编辑:正如评论中指出的那样,通常不希望这样做。
  • 鉴于常量经常一起访问,我们可以在需要时为结构创建简写形式以提高可读性,即:static const auto & SHORTHAND = SomeClass::LONG_NAME_FOR_CONSTANTS;

使用此模式时有什么缺点,陷阱或其他注意事项?

2 个答案:

答案 0 :(得分:5)

(A)可能很难通过从最终可执行文件中删除不必要的变量来进行优化。

如果要对常量进行分组,请考虑为此使用namespace

namespace ConstantGroup
{
    constexpr int a = 1;

    // Here best solution might depend on usage and c++ version
    const std::string b;    
}

将常量作为一个组进行传递确实没有多大意义。如果某些内容确实是常量,那么您需要一个定义并始终使用它。

如果常量非常特定于一个类,则将其设为该类的(静态)成员。

答案 1 :(得分:1)

有趣(继与@Henri Menke在上面的评论中有关stringstring_view s的对话之后。

为此:

#include <string>
#include <string_view>
#include <iostream>

static const std::string a = "a";
static const std::string_view b = "b";

int main ()
{
    std::cout << a << "\n";
    std::cout << b << "\n";
}

您可以在Godbolt清楚地看到,构造a需要运行时初始化程序,而b是编译时常量。

如果您不喜欢阅读编译器生成的代码,请尝试将两个const更改为constexpr。然后,std::string_view仍会编译,而std::string不会。

因此,对于静态和/或全局常量字符串,constexpr std::string_view = "blah blah blah";似乎是Henri所说的一个很好的解决方案,因为它在老式的C字符串上提供了相当多的extra functionality如果,您可以使用C ++ 17 并且,您无需担心在上下文中将它们转换为std::string(这将涉及构造一个)的成本那是代码中当时需要的地方。

否则,您将被迫退回到std::string或普通的旧C字符串。


编辑:

在研究此问题时,我注意到std::stringview中有一个奇怪的缺点:它不提供operator std::string ()方法。我不知道为什么不这样做,但是例如,这意味着以下内容不会编译:

void foo (std::string s)
{
    ...
}

std::string_view sv = ...;
foo (sv);

我说这还不够好,所以本着分享的精神(如果有人还在看这本书),我谨此向您提供:

#include <string>
#include <string_view>

template <class T> struct MyBasicStringView : public std::basic_string_view <T>
{
    constexpr MyBasicStringView (const T *s) : std::basic_string_view <T> (s) { }
    operator std::basic_string <T> () const { return std::basic_string <T> (this->data ()); }
};

using MyStringView = MyBasicStringView <char>;

测试程序:

static constexpr MyStringView a_static_string_view = "static_string";

std::string foo (std::string s)
{
    return s + " x";
}

#include <iostream>

int main ()
{
    std::cout << a_static_string_view << "\n";
    MyStringView sv = "abcde";
    std::cout << sv << "\n";
    std::cout << foo (sv) << "\n";
}

输出:

static_string
abcde
abcde x

Live demo