空值包扩展是否与类型包或可选类型参数匹配
Does an empty value pack expansion match a type pack or optional type parameter?
我只是想破解一个二进制文字operator ""_b
,但在尝试终止递归时遇到了困难。如何定义一个可以使用空的显式模板参数列表调用的函数,该列表与参数包重载不冲突?然后,灵感:将空包资料片与一些古怪的东西相匹配。
但GCC抱怨说,不存在的空参数列表类型和不明确要求的参数列表类型不一致。它应该这样工作吗?
template< char head, char ... tail >
constexpr unsigned long long parse_binary() {
return ( ( head - '0' ) << sizeof ... (tail) )
+ parse_binary< tail ... >(); // Error: no overload for termination.
}
template< typename = void > // I want this to match an empty pack of chars.
// template< short = 0 > // even this would do.
constexpr unsigned long long parse_binary() {
return 0;
}
template< char ... digits >
constexpr unsigned long long operator ""_b() {
return parse_binary< digits ... >();
}
#include <iostream>
int main() {
std::cout << 010101_b << 'n';
}
注意:问题不是实现operator ""_b
。这个问题可以通过将包扩展到参数列表中并传递std::integral_constant
类型来解决。
注2:此代码实际上只需进行小的调整即可工作;请看下面的答案。但这并不能直接解决问题。嗯,也许我应该编辑这个而不是回答…
在一个字符处终止递归不是更好吗?
template<char Ch>
constexpr unsigned long long parse_binary(){
return Ch - '0';
};
// second head to disambiguate
template< char head1, char head2, char ... tail >
constexpr unsigned long long parse_binary() {
return ( ( head1 - '0' ) << sizeof ... (tail)+1 ) + parse_binary< head2, tail ... >();
}
无论如何,问题是零字符的parse_binary
需要在可变版本之前声明,正如Clang很好地指出的那样:
error: call to function 'parse_binary' that is neither visible in
the template definition nor found by argument-dependent lookup
// call trace...
note: 'parse_binary' should be declared prior to the call site
constexpr unsigned long long parse_binary() {
没有关于这种棘手匹配的合规性的官方说法,但如果两个重载互换,给定的代码确实有效。
第二个终止重载对第一个重载不可见,因为第一个重载在模板定义时解析名称。只有依赖于模板参数的函数调用的查找延迟到实例化时。
需要明确的是,这是有效的:
template< typename = void > // Define this one first!
constexpr unsigned long long parse_binary() {
return 0;
}
template< char head, char ... tail >
constexpr unsigned long long parse_binary() {
return ( ( head - '0' ) << sizeof ... (tail) )
+ parse_binary< tail ... >(); // Bingo: overload found.
}
相关文章:
- 扩展C++生成的代码的模板参数类型名称
- 在 c++ 中的模板实例化中使用带有构造函数的类作为类型参数
- 如何解决一元"*"(有"字符")错误的无效类型参数?
- 如何在 c++ 中定义接受不同参数类型的函数向量?
- "std::shared_ptr":不是参数"_Ty"的有效模板类型参数
- 在 C++ 中运行时调用模板时,是否可以切换模板的参数类型?
- 具有可变参数非类型参数的模板专用化
- 函数类型参数的模板参数推导
- 将函数参数类型声明为 auto
- 将函数的参数 - 签名从使用 'std::function<T>' 转换为模板参数类型
- 在 C++17 中调用具有不同参数类型的构造函数
- 具有先前参数类型匹配的参数包
- 我想知道为什么"std::unique_ptr<int> foo(新 int)"是合法的,因为"std::<int>unique_ptr"要求输入参数类型应该是"int"?
- PowerShell 使用结构类型参数调用 C++ DLL 的导出函数
- 将可变参数类型列表的扩展打包为复杂类型的初始值设定项列表 - 合法吗?
- MSVC 错误:4 个重载中的任何一个都无法转换所有参数类型
- 使用constexpr + auto作为返回和参数类型的奇怪类型推导
- 如何从第一个参数推断第二个参数类型?
- C++ 按非类型参数类型划分的模板专用化
- 模板类型参数类型