C++ 将 std::source_location::function_name() 作为字符串文字模板参数传递

c++ pass std::source_location::function_name() as string literal template argument

提问人:Dmitry Logov 提问时间:10/23/2023 最后编辑:Jarod42Dmitry Logov 更新时间:10/23/2023 访问量:108

问:

我有这段代码,它返回宏在编译时提供的修改后的函数名称字符串:__PRETTY_FUNCTION__

template<size_t N>
struct SL
{
    char value[N];
    constexpr SL(const char (&str)[N])
    {
        for(size_t i = 0; i != N; ++i)
            value[i] = str[i];
    }
};

template<SL literal>
consteval auto PrettifyFunctionName()
{
    ...
}

我是这样使用它的:

constexpr auto resultName = PrettifyFunctionName<__PRETTY_FUNCTION__>();

我想用std::source_location::function_name()替换宏 如何将其作为模板参数传递?
有没有另一种方法可以将其作为 PrettifyFunctionName 中的值获取?
__PRETTY_FUNCTION__constexpr

C++ 模板 constexpr

评论

1赞 Pepijn Kramer 10/23/2023
const char*不是有效的模板参数类型。但是,您应该能够制作一个函数constexpr auto PrettifyFunctionName(const char* function_name)
1赞 Jarod42 10/23/2023
或者:使用 .consteval auto PrettifyFunctionName(std::source_location)constexpr auto resultName = PrettifyFunctionName(std::source_location::current());
0赞 Red.Wave 10/23/2023
@Jarod42源位置函数必须作为其参数的默认值。这就是魔术的运作方式。= std::source_location::current()
0赞 chris 10/23/2023
@Red.Wave,虽然我推荐这种方法,但唯一的魔力是,如果没有编译器钩子,你就无法实现。默认参数仅依赖于预先存在的语言规则,即在调用站点评估默认值,因此使参数显式执行相同的操作。std::source_location
0赞 Red.Wave 10/23/2023
@chris看一下 的实现。你猜怎么着:这也依赖于默认参数。因为太多的编译器魔术是不可取的。current()

答:

1赞 user17732522 10/23/2023 #1

添加一个构造函数,该构造函数从 复制到数组中,就像当前循环一样,然后:SLconst char*

constexpr auto funcName = std::source_location::current().function_name();
constexpr auto resultName = PrettifyFunctionName<SL<mystrlen(funcName)+1>(funcName)>();

您将需要与自己等效地定义,因为没有标记 .mystrlenstrlenstd::strlenconstexpr

无法避免两次命名,因为它的类型不包含有关其长度的信息,并且未指定结果是否引用字符串文本。如果它引用字符串文本,则不能直接作为模板参数传递。funcNamefunction_name

但是,您可以用一些足够大的数字替换。如果实际函数名称太长,它将无法编译。mystrlen(funcName)+1

将字符串作为函数参数而不是模板参数传递可能更容易,假设您不需要字符串成为 later 类型的一部分。resultName


顺便说一句,我认为编译时的使用没有很好地指定。source_location

标记成员函数,指示它们应该在编译时可用,但结果仅指定为引用某些以 null 结尾的字节字符串。constexprfunction_name

它没有说明该字符串是否应该具有静态存储持续时间,以便指针可以存储在变量中,它是否可以引用字符串文字,以便它不能直接用作模板参数,以及它的元素是否可以在常量表达式中使用,以便可以在常量表达式中检查字符串的实际内容。(虽然第一种是从被标记中得出的。constexprcurrentconsteval

但一个普遍的问题是,标记的库函数缺乏精确的规范,哪些是保证编译时使用的,哪些是不能的。constexpr

评论

0赞 Yksisarvinen 10/23/2023
Jason Turner 有一个很长的视频,讲述了在编译时一起获取具有长度的 const char* 的问题:youtube.com/watch?v=ABg4_EV5L3w(不是说你的方法是错误的,只是为任何对这个问题感兴趣的人添加额外的绒毛)
0赞 user17732522 10/23/2023
@Yksisarvinen我还没有看过,但稍后会看。还有一些技巧可以应用来让它看起来更好,但对于这个用例,还有一些额外的约束,因为字符串必须从这个函数的调用中获取,而不是例如在 lambda 中。source_location