c++ constexpr字符串文字作为标识符

cx6n0qe3  于 2023-01-28  发布在  其他
关注(0)|答案(2)|浏览(213)

有时我喜欢使用static const char*/static const char[]作为标识符而不是枚举,字符串文字指针的可靠性很好。
最近我一直在想,是否可以依赖constexpr方法每次都返回相同的指针?具体来说:

struct traits_like
{
   static constexpr const char* id() { return "special traits"; }
}

另外,在这种情况下,类似constexpr const char* id = "special traits"constexpr char[] id的做法是否更好?
更新:
在我的用例中,我会有许多通过模板找到的traits(如类),因此理论上会看到类似TTraits1::id() == TTraits2::id()的东西

xqkwcwgp

xqkwcwgp1#

CWG 1823的解决方案阐明了即使对相同的字符串常量进行重复求值也不必生成相同的字符串常量对象,特别是内联函数不必在不同的翻译单元或重复调用中返回相同的指针地址。
此外,多个字符串对象可能使用重叠存储,因此两个指向字符串的指针相等也不意味着它们具有相同的值。

knpiaxh1

knpiaxh12#

为了更好地实践,我建议使用std::string_view,例如:

struct A {
    constexpr static std::string_view name = "A";
};

这是一个干净和简单的方式,更重要的是-给你一个方便的界面。
更完整的示例:

#include <iostream>
#include <concepts>
#include <string_view>

struct A {
    constexpr static std::string_view name = "A";
};

struct B {
    constexpr static std::string_view name = "B";
};

struct OtherStruct {
    constexpr static std::string_view name = "OtherStruct";
};

template <typename T>
concept struct_with_name = requires {
    { T::name } -> std::same_as<const std::string_view&>;
};

template <struct_with_name T>
void print_struct([[maybe_unused]] const T& input) {
    std::cout << "Name: " << T::name << "\n";
}

int main()
{
    print_struct(A{});
    print_struct(B{});
    print_struct(OtherStruct{});
}

预期结果:

Name: A
Name: B
Name: OtherStruct

传递不带name的结构将导致编译错误:

(...)
<source>:23:6: note: constraints not satisfied
<source>: In substitution of 'template<class T>  requires  struct_with_name<T> void print_struct(const T&) [with T = NoName]':
(...)
<source>:19:10: note: the required expression 'T::name' is invalid
   19 |     { T::name } -> std::same_as<const std::string_view&>;

在我的用例中,我会有许多通过模板找到的traits类,因此理论上会看到类似于TTraits1::id()== TTraits2::id()的内容
使用上例中的元素,您可以简单地执行以下操作:

if constexpr (A::name == B::name) {
    std::cout << "The same...\n";
} else {
    std::cout << "Not the same...\n";
}

相关问题