c++ - std::source_location 作为非类型模板参数

标签 c++ c++20 std-source-location

在我无限追求突破可用作非类型模板参数的限制时,我试图看看是否可以使用 std::source_location 作为非类型模板参数。 失败并出现一条奇怪的消息,因为我认为 source_location 是一些神奇的结构......

type 'std::experimental::source_location' of non-type template parameter is not a structural type

它失败了,所以我尝试使用 .file_name 来解决这个问题,但这也失败了( godbolt )。

note: candidate template ignored: substitution failure: pointer to subobject of string literal is not allowed in a template argument

#include<iostream>
#include<experimental/source_location>

template<auto src_loc = std::experimental::source_location::current().file_name()>
void log_first(){
    static bool dummy =([]{
        std::cout << "Logging first call" + src_loc << std::endl;
    }(), false);
}

int main() {
    log_first();
    log_first();
}

有什么方法可以在不使用宏的情况下完成这项工作吗?

需要明确的是,我是在询问如何使用 source_location 作为模板参数,而不是解决我的玩具示例,它只是在这里演示潜在的用例。

最佳答案

std::source_location指定为:

  struct source_location {
    // ...

  private:
    uint_least32_t line_;               // exposition only
    uint_least32_t column_;             // exposition only
    const char* file_name_;             // exposition only
    const char* function_name_;         // exposition only
  };

可用作非模板模板参数的类型类型的规则要求类型是结构性的,这意味着,从 [temp.param]/7 ,强调我的:

A structural type is one of the following:

  • a scalar type, or
  • an lvalue reference type, or
  • a literal class type with the following properties:
    • all base classes and non-static data members are public and non-mutable and
    • the types of all bases classes and non-static data members are structural types or (possibly multi-dimensional) array thereof.

source_location 并未将其所有非静态数据成员公开,因此它不是结构性的,因此它不能用作非类型模板参数。


这部分:

template <auto src_loc = std::experimental::source_location::current().file_name()>

由于[temp.arg.nontype]/3而无法工作:

For a non-type template-parameter of reference or pointer type, or for each non-static data member of reference or pointer type in a non-type template-parameter of class type or subobject thereof, the reference or pointer value shall not refer to or be the address of (respectively):

  • [...],
  • a string literal object ([lex.string]),
  • ...

但是您可以做的是创建自己的类型,即结构性类型,可以从 source_location 构造。只是字符串不能是 char const* ,它们必须拥有数据。如果您查看 P0732 中的示例,我们可以建立:

template <typename Char, size_t N>
struct basic_fixed_string { ... };

template <basic_fixed_string S> struct A {};

using T = A<"hello">;

在这种情况下处理起来可能会很尴尬,因此您也可以选择一些合理的最大尺寸并使用它。

关于c++ - std::source_location 作为非类型模板参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65203441/

相关文章:

c++ - 在 Linux 上使用 QTCreator IDE 的文件 IO

c++ - 将返回表达式隐式转换为 bool

c++ - 为什么 C++ lambda 重载的行为不如预期?

c++ - 是否可以使用范围适配器将投影成员恢复为原始类对象?

c++ - 使用结构化绑定(bind)的“反射”

c++ - 是否可以使作为默认参数的宏在调用站点展开?

c++ - 已连接串口C列表Qt

c++ - cocos2d-x 3 以不推荐的方式创建标签

c++ - Visual Studio 中的 std::experimental::source_location 实现