根据 Piotr Skotnicki 的建议,一个简单的解决方案是将第一个参数与以下参数分开,并使用 && 作为折叠运算符进行检查
例如,如果所有参数都相等,则以下函数返回 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 拆分为a0 和以下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()和bar()的返回指令可以写成无所谓
return ( (args == a0) && ... && true );
或
return ( (args == a0) && ... );
sizeof...(args) == 0U 也是如此。
但我倾向于忘记这类细节,更喜欢显式(使用最后的&& true)空值。