【发布时间】:2020-11-15 22:57:38
【问题描述】:
以下代码使用多个参数包来定义一个可变参数模板累加器函数,该函数接受任何数值类型或指向数值类型的指针:
// Compile with --std=c++20
#include <type_traits>
template <typename T>
concept number = std::is_arithmetic_v<T>
&& !std::is_pointer_v<T>;
template <typename T>
concept pointer = std::is_arithmetic_v<std::remove_pointer_t<T>>
&& std::is_pointer_v<T>;
double foo ()
{return 0;}
double foo (pointer auto p0)
{return *p0;}
double foo (pointer auto p0,
pointer auto ... ps)
{return *p0 + foo (ps ...);}
double foo (number auto n0,
pointer auto ... ps)
{return n0 + foo (ps ...);}
double foo (number auto n0,
number auto ... ns, /* <---- THIS LINE */
pointer auto ... ps)
{return n0 + foo (ns ..., ps ...);}
int main()
{
float f = 3.;
unsigned u = 4;
foo (); // Compiles
foo (1); // Compiles
foo (&f); // Compiles
foo (1, &f); // Compiles
foo (1, &f, &u); // Compiles
foo (&f, &u); // Compiles
foo (1, 2.); // Error!
foo (1, 2., &f); // Error!
foo (1, 2., &f, &u); // Error!
}
当有多个number 类型的参数时触发错误。
看起来当有多个参数包时,编译器将所有参数打包在最后一个包中,而不是引用约束来定义哪个参数属于哪个参数包。
这是语言的限制吗?多个参数包是否意味着以其他方式使用?有什么解决方法可以让它工作吗?
在 clang 和 GCC 中测试
更新:已解决!
解决方案:使用单个参数包,不约束参数包,逐个约束参数的类型。
// Compile with --std=c++20
#include <type_traits>
template <typename T>
concept number = std::is_arithmetic_v<T>;
template <typename T>
concept pointer = std::is_arithmetic_v<std::remove_pointer_t<T>>
&& std::is_pointer_v<T>;
double foo ()
{return 0;}
double foo (pointer auto p0)
{return *p0;}
double foo (pointer auto p0,
pointer auto ... ps)
{return *p0 + foo (ps ...);}
template <typename ... N_P>
double foo (number auto n0,
N_P ... ps)
{return n0 + foo (ps ...);}
int main()
{
float f = 3.;
unsigned u = 4;
foo (); // Compiles
foo (1); // Compiles
foo (&f); // Compiles
foo (1, &f); // Compiles
foo (1, &f, &u); // Compiles
foo (&f, &u); // Compiles
foo (1, 2.); // Good!
foo (1, 2., &f); // Good!
// foo (1, &f, 2.); // Does not compile (Good!)
return foo (1, 2., &f, &u); // Good!
}
【问题讨论】:
-
一个类型不能同时是算术和指针,所以
std::is_arithmetic_v<T> && !std::is_pointer_v<T>是多余的。 -
"多个参数包是不是打算以其他方式使用?" 广义上讲,多个函数参数包根本不打算使用 i>.
标签: c++ overloading variadic-templates c++20 c++-concepts