std :: source_location作为非类型模板参数 [英] std::source_location as non type template parameter
问题描述
在无穷无尽的尝试中,尝试限制可以用作非类型模板参数的值,我试图查看是否可以将 std :: source_location
用作非类型模板参数.由于我认为source_location是一些神奇的结构,因此失败并发出一条奇怪的消息.
In my infinite quest to push limits of what can be used as non type template parameter I was trying to see if I can use std::source_location
as non type template parameter.
That failed with a weird message, since I presume source_location is some magical struct...
非类型模板的类型'std :: experimental :: source_location'参数不是结构类型
type 'std::experimental::source_location' of non-type template parameter is not a structural type
它失败了,所以我尝试使用.file_name来解决,但这也失败了( godbolt ).
It failed, so I tried to workaround that with using .file_name, but that also fails (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();
}
有什么方法可以在不使用宏的情况下完成这项工作?
Is there any way to make this work without use of macros?
要清楚,我要问的是使用 source_location
作为模板参数,而不是解决我的玩具示例,这只是在演示潜在的用例.
To be clear I am asking about using source_location
as template parameter, not about solving my toy example, it is just here to demonstrate potential use case.
推荐答案
并且可用作非模板模板参数的类型类型的规则要求类型为 structural ,这意味着从
And the rules for the kinds of types that can be used as non-template template parameters require that a type be structural, which means, from [temp.param]/7, emphasis mine:
结构类型是以下之一:
- 标量类型,或
- 左值引用类型,或
- 具有以下属性的文字类类型:
- 所有基类和非静态数据成员都是公开的,并且不可更改,并且
- 所有基类和非静态数据成员的类型是结构类型或其(可能是多维)数组.
source_location
并没有公开其所有非静态数据成员,因此它不是结构化的,因此不能用作非类型模板参数.source_location
does not have all of its non-static data members public, so it is not structural, so it is not usable as a non-type template parameter.此部分:
template <auto src_loc = std::experimental::source_location::current().file_name()>
对于引用或指针类型的非类型模板参数,或对于类类型或其子对象的非类型模板参数中的引用或指针类型的每个非静态数据成员,引用或指针值不得分别引用或作为以下地址:
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):
- [...],
- 字符串文字对象([lex.string]),
- ...
但是您可以做的是创建自己的结构类型,可以从
source_location
中构造该类型.只是字符串不能是char const *
,它们必须拥有数据.如果您查看 P0732 中的示例,我们可以构建:
But what you can do is create your own type, that is structural, that is constructible from
source_location
. It's just that the strings can't bechar const*
, they have to own the data. If you look in the examples in P0732, we can build up:template <typename Char, size_t N> struct basic_fixed_string { ... }; template <basic_fixed_string S> struct A {}; using T = A<"hello">;
在这种情况下,处理起来可能很尴尬,因此您也可以选择一些合理的最大尺寸,然后选择该尺寸.
That might be awkward to deal with in this case, so you could also just pick some reasonable max size and go with that.
这篇关于std :: source_location作为非类型模板参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!