在编译时仅接受指向静态存储字符串文字的 string_view,无需模板

问题描述 投票:0回答:1

背景

  1. 有一个类使用不同的回调和不同的数据集,并希望为它们提供不同类型的“名称”来进行日志记录。
X kind of Data: [email address, geo address, user name]
Y kind of evaluation: [starts_with, hash, ends_with, ...etc ]
  1. 这与具有不同类型的数据和逻辑的不同“类型”的对象非常相似。因此,使用枚举会很乏味,因为
    X
    种数据和
    Y
    评估可能会导致
    X*Y
    数量的组合。

我想要一些用于记录指向某些静态存储字符串文字的代码。 从构造函数中获取一个简单的

std::string_view
到私有成员似乎没问题,但我想防止未来的维护者提供非静态存储字符串...

注意:这似乎是 C++:构造函数仅接受字符串文字的重复,但答案是写在模板中的。

目标和假设:

  1. 编译时会有已知数量的静态字符串文字。
  2. 多个对象将指向相同的静态字符串文字,我想避免使用
    std::string
  3. 避免
    std::string_view
    指向临时数据。

到目前为止使用模板或枚举的解决方案:

  1. 模板参数的字符串文字
  2. 作为模板参数的回调 但我不想编写模板代码只是为了使用名称进行日志记录...
  3. 使用
    enum
    并在日志记录中查找枚举也可以。我厌倦了在字符串中添加枚举和反向查找枚举...如果没有其他解决方案,这将是我的最终解决方案。

解决方案要求:

  1. 接受C++20及以上的解决方案。即使它是在 C++23 或 C++26 中,至少我知道它可以在将来得到解决。感谢是否有 C++20 的解决方案。
  2. 也许这是一个 XY 问题。如果有其他方法可以解决请告诉我。

无限制现场演示

#include <iostream>
#include <string_view>

static constexpr std::string_view EXACT = "exact";
static constexpr std::string_view PREFIX = "prefix";

class Evaluator{
public:
    Evaluator(std::string_view name) : m_name(name){}
    bool evaluate(std::string_view input){
        // Work for lookup per input
        // ...
        // Logging
        std::cout << m_name << "\n";
        return true;
    }
private:
    std::string_view m_name;

};

int main(){
    Evaluator exact(EXACT);
    exact.evaluate("");
    Evaluator prefix(PREFIX);
    prefix.evaluate("");
}

模板版本现场演示

static constexpr const char CEXACT[] = "exact";
static constexpr const char CPREFIX[] = "prefix";

template<const char* name>
class Evaluator{
public:
    Evaluator() : m_name(name){}
    bool evaluate(std::string_view input){
        // Work for lookup per input
        std::cout << m_name << "\n";
        return true;
    }
private:
    std::string_view m_name;
};

c++ string c++20
1个回答
0
投票

使用编译时字符串实现。 这是一个包含实际字符串的对象,并且始终是

consteval

编写一个伪字符串视图来包装这样的编译时字符串。

第一个是模板类(以免浪费存储空间)。 第二个将具有来自所述模板类的模板构造函数,但内部只是一对指针。 您甚至可以在内部使用

string_view
,具有不同程度的 DRY 故障和/或可能的“安全漏洞”,以允许某人主动绕过类型限制。

使用看起来像:

static constexpr ct_string EXACT = "exact";
static constexpr ct_string CPREFIX = "prefix";

static constexpr auto EXACT = "exact"_ct;
static constexpr auto CPREFIX = "prefix"_ct;

消费时:

bool evaluate(ct_string_view input){
  // Work for lookup per input
  std::cout << m_name << "\n";
  return true;
}

在内部,

ct_string
最终成为一个以空字符结尾的保守数组。

© www.soinside.com 2019 - 2024. All rights reserved.