正如 Piotr Skotnicki 所建议的那样,一个简单的解决方案是将第一个参数与以下参数分开,并使用&&
as fold 运算符对其进行检查
true
例如,如果所有参数都相等,则返回以下函数
template <typename A0, typename ... Args>
bool foo (A0 const & a0, Args const & ... args)
{ return ( (args == a0) && ... && true ); }
不幸的是,这不适用于空的参数列表
std::cout << foo(1, 1, 1, 1) << std::endl; // print 1
std::cout << foo(1, 1, 2, 1) << std::endl; // print 0
std::cout << foo() << std::endl; // compilation error
但您可以添加特殊的空参数foo()
bool foo ()
{ return true; }
如果由于某种原因,您不能将args
aa0
和以下分开args
?
嗯……你显然可以使用前面的foo()
函数(有特殊的空版本)
template<typename... Args>
void func (Args... args)
{
ASSERT (foo(args));
// more code here...
}
或者您可以使用带有逗号运算符和赋值的 C++17 折叠表达式,如下所示bar()
template <typename ... Args>
bool bar (Args const & ... args)
{
auto a0 = ( (0, ..., args) );
return ( (args == a0) && ... && true );
}
观察a0
分配中的初始零,它允许使用这个解决方案,也可以使用一个空的参数列表。
不幸的是,从前面的auto a0
分配中,我得到了很多我不知道如何避免的警告(“表达式结果未使用”,来自 clang++,和“逗号运算符的左操作数无效”,来自 g++)。
以下是一个完整的工作示例
#include <iostream>
template <typename A0, typename ... Args>
bool foo (A0 const & a0, Args const & ... args)
{ return ( (args == a0) && ... && true ); }
bool foo ()
{ return true; }
template <typename ... Args>
bool bar (Args const & ... args)
{
auto a0 = ( (0, ..., args) );
return ( (args == a0) && ... && true );
}
int main ()
{
std::cout << foo(1, 1, 1, 1) << std::endl; // print 1
std::cout << foo(1, 1, 2, 1) << std::endl; // print 0
std::cout << foo() << std::endl; // print 1 (compilation error
// witout no argument
// version)
std::cout << bar(1, 1, 1, 1) << std::endl; // print 1
std::cout << bar(1, 1, 2, 1) << std::endl; // print 0
std::cout << bar() << std::endl; // print 1 (no special version)
}
- 编辑 -
正如 dfri 所指出的(谢谢!),对于和空args...
包,以下折叠表达式的值
( (args == a0) && ... )
( (args == a0) || ... )
分别是true
和false
。
foo()
所以and的返回指令bar()
可以写成
return ( (args == a0) && ... && true );
或者
return ( (args == a0) && ... );
万一也是如此sizeof...(args) == 0U
。
但我倾向于忘记这种细节,更喜欢显式(使用 final && true
)空值。