考虑以下代码:
struct Base_string { char data[1 << 5]; };
template<typename Base>
struct Derived: Base { };
Derived(char const*) -> Derived<Base_string>;
template<Derived>
struct S { };
S<{"Test"}> s; // Error
Run Code Online (Sandbox Code Playgroud)
最后一行被S实例化,无法编译。我希望它能起作用,因为[temp.arg.nontype#1]指出:
如果模板参数的类型 T 包含 [...] 推导类类型的占位符,则参数的类型是为发明声明中的变量 x 推导的类型
T x = template-argument;
就我而言,这个发明的声明看起来像这样:Derived x = {"Test"};,并且实际上在程序中声明这样的变量不会产生错误 - 类型被正确推导。
另外,我认为问题不在于聚合初始化语法本身 - 将模板的定义更改S为:
template<Base_string>
struct S { };
Run Code Online (Sandbox Code Playgroud)
并以相同的方式实例化它 ( S<{"Test"}> s;) 不会产生错误。
我知道我可以简单地显式指定类型,如下所示:S<Derived{"Test"}> s;,但我不是在寻找解决方法,我想了解为什么推导在这里失败。
让我们定义以下模板:
template<typename> concept C_one = true;
template<typename...> concept C_many = true;
template<bool> struct S { };
Run Code Online (Sandbox Code Playgroud)
现在,让我们尝试使用它们。
这一行编译:
template<typename T = S<C_one<int>>> void f() { }
Run Code Online (Sandbox Code Playgroud)
而这个则没有:
template<typename T = S<C_many<int>>> void f() { }
Run Code Online (Sandbox Code Playgroud)
我收到的错误是:
error: type/value mismatch at argument 1 in template parameter list for 'template<bool <anonymous> > struct S'
Run Code Online (Sandbox Code Playgroud)
我注意到用C_many<int>括号括起来可以解决这个问题,但是这种看似不一致的语法的原因是什么?我认为错误消息也没有多大帮助。
另外,我知道这可能是一个非常人为的示例,因为我尝试创建一个最小的可重现示例。
regex我想构建一个关于in的所有子匹配的视图text。以下是定义此类视图的两种方法:
char const text[] = "The IP addresses are: 192.168.0.25 and 127.0.0.1";
std::regex regex{R"((\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3}))"};
auto sub_matches_view =
std::ranges::subrange(
std::cregex_iterator{std::ranges::begin(text), std::ranges::end(text), regex},
std::cregex_iterator{}
) |
std::views::join;
auto sub_matches_sv_view =
std::ranges::subrange(
std::cregex_iterator{std::ranges::begin(text), std::ranges::end(text), regex},
std::cregex_iterator{}
) |
std::views::join |
std::views::transform([](std::csub_match const& sub_match) -> std::string_view { return {sub_match.first, sub_match.second}; });
Run Code Online (Sandbox Code Playgroud)
sub_matches_view的值类型是std::csub_match. 它是通过首先构造对象视图std::cmatch(通过正则表达式迭代器)来创建的,并且由于每个对象std::cmatch都是一系列std::csub_match对象,因此它被展平为std::views::join.sub_matches_sv_view的值类型是std::string_view. 它与 相同,只是它也包装了a 中sub_matches_view的每个元素。sub_matches_viewstd::string_view以下是上述范围的使用示例:
for(auto const& sub_match : sub_matches_view) …Run Code Online (Sandbox Code Playgroud) 我正在浏览 GCC 11.2 标头的实现<optional>(可以在此处找到),我注意到一些我很难理解的东西。这是标题(希望)只留下了重要的部分:
#ifndef _GLIBCXX_OPTIONAL
#define _GLIBCXX_OPTIONAL 1
#pragma GCC system_header
#if __cplusplus >= 201703L
/* Includes of various internal and library headers */
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
#if __cplusplus == 201703L
# define __cpp_lib_optional 201606L
#else
# define __cpp_lib_optional 202106L
#endif
/* Implementation */
template<typename _Tp>
class optional;
/* Implementation */
template<typename _Tp>
class optional: /* Implementation */
{ /* Implementation */ };
/* Implementation */
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // …Run Code Online (Sandbox Code Playgroud)