constexpr字符串字面值作为标识符



有时我喜欢使用static const char*/static const char[]作为标识符而不是枚举。string literal指针的可靠性很好。

最近我一直在想,可以依靠constexpr方法每次返回一个相同的指针吗?具体来说:

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

还有,我想在这种情况下,constexpr const char* id = "special traits"constexpr char[] id是更好的做法?

更新:

在我的用例中,我会有许多特性,比如通过模板找到的类,所以理论上会看到像TTraits1::id() == TTraits2::id()

这样的东西

CWG 1823的决议明确了即使对相同的字符串字面值重复求值也不一定产生相同的字符串字面值对象。特别是,内联函数不必在不同的转换单元或重复调用中返回相同的指针地址。

此外,多个字符串文字对象可能使用重叠存储。因此,两个指向字符串字面值的指针相等并不意味着它们具有相同的值。

为了更好的实践,我建议使用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的struct将导致编译错误:

(...)
<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&>;

在我的用例中,我将有许多特性——比如类在我的用例中飞来飞去通过模板查找,所以理论上会看到类似的东西TTraits1::id() == TTraits2::id()

使用上面例子中的元素,您可以简单地这样做:

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

最新更新