std::source_location 作为非类型模板参数
std::source_location as non type template parameter
在我无限探索可以用作非类型模板参数的极限的过程中,我试图看看我是否可以使用 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
没有它所有的非静态数据成员 public,所以它不是结构化的,所以它不能用作非类型模板参数。
这部分:
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">;
在这种情况下处理起来可能很尴尬,因此您也可以选择一些合理的最大尺寸并使用它。
在我无限探索可以用作非类型模板参数的极限的过程中,我试图看看我是否可以使用 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
没有它所有的非静态数据成员 public,所以它不是结构化的,所以它不能用作非类型模板参数。
这部分:
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">;
在这种情况下处理起来可能很尴尬,因此您也可以选择一些合理的最大尺寸并使用它。