特别是Clang 3.6.0,目前由Coliru主持.
所有这些片段都来自:
int main() {
foo();
std::cout << "\n----\n";
foo(1, 2, 3);
}
Run Code Online (Sandbox Code Playgroud)
以下代码:
template <class... Args>
void foo(Args... args) {
std::cout << ... << args;
}
Run Code Online (Sandbox Code Playgroud)
触发以下编译错误:
main.cpp:7:17: error: expected ';' after expression
std::cout << ... << args;
^
;
main.cpp:7:15: error: expected expression
std::cout << ... << args;
^
Run Code Online (Sandbox Code Playgroud)
所以我试着在表达式周围添加括号:
(std::cout << ... << args);
Run Code Online (Sandbox Code Playgroud)
它有效,但会触发警告:
main.cpp:7:6: warning: expression result unused [-Wunused-value]
(std::cout << ... << args);
^~~~~~~~~
main.cpp:11:5: note: in instantiation of function template specialization 'foo<>' …Run Code Online (Sandbox Code Playgroud) 请考虑以下最小示例:
#include<cstddef>
template<std::size_t... I>
constexpr auto sum() { return (I + ...); }
template<bool... B>
constexpr auto check() { return (B && ...); }
int main() {
static_assert(6 == sum<1,2,3>(), "!");
// static_assert(0 == sum<>(), "!");
static_assert(check<true, true>(), "!");
static_assert(check<>(), "!");
}
Run Code Online (Sandbox Code Playgroud)
注释行不编译.
这同样适用于*代替+.
涉及布尔运算的那个相反.
这里(工作草案)我没有找到关于空参数包的提及.
另一方面,这里(isocpp)似乎是上面例子中的默认结果int().
混合折叠表达式和空参数包时,预期的行为是什么?
N4191提出了C++的fold-expressions.有那样的定义
(args + ...)
Run Code Online (Sandbox Code Playgroud)
是左折(即(((a0 + a1) + a2) + ...),那个
(... + args)
Run Code Online (Sandbox Code Playgroud)
是一个右折(即(... + (a8 + (a9 + a10))).然而,修订后的论文N4295颠倒了左右一元褶的定义.
问题:理由是什么?它似乎更直观(至少当你习惯于从左到右的字母表)从左到右进行评估(args + ...).
在C++ 17中,fold表达式可用,因此要打印参数,我们可以使用
#define EOL '\n'
template<typename ...Args>
void output_argus(Args&&... args)
{
(cout << ... << args) << EOL;
}
int main()
{
output_argus(1, "test", 5.6f);
}
Run Code Online (Sandbox Code Playgroud)
有输出
1test5.6
如果我想使用fold表达式'\n'为每个元素添加额外的字符以获得以下结果,该怎么办?
1
test
5.6
Run Code Online (Sandbox Code Playgroud)
这甚至可能吗?如果有,怎么样?
我正在看看C++ 17 折叠表达式,我想知道为什么以下程序输出
4 5 6
4 5 6
Run Code Online (Sandbox Code Playgroud)
对于这两个for_each电话
template<typename F, typename... T>
void for_each1(F fun, T&&... args)
{
(fun (std::forward<T>(args)), ...);
}
template<typename F, typename... T>
void for_each2(F fun, T&&... args)
{
(..., fun (std::forward<T>(args)));
}
int main()
{
for_each1([](auto i) { std::cout << i << std::endl; }, 4, 5, 6);
std::cout << "-" << std::endl;
for_each2([](auto i) { std::cout << i << std::endl; }, 4, 5, 6);
}
Run Code Online (Sandbox Code Playgroud)
我认为第二个折叠表达式意味着以相反的顺序输出数字
6 5 4 …Run Code Online (Sandbox Code Playgroud) 以下是合法的表达式吗?
template <std::size_t N, std::size_t... Ix>
bool in_range(std::index_sequence<Ix...>) {
return ((Ix < N) && ...);
}
Run Code Online (Sandbox Code Playgroud)
C++ 17折叠表达式的经典示例是打印所有参数:
template<typename ... Args>
void print(Args ... args)
{
(cout << ... << args);
}
Run Code Online (Sandbox Code Playgroud)
例:
print("Hello", 12, 234.3, complex<float>{12.3f, 32.8f});
Run Code Online (Sandbox Code Playgroud)
输出:
Hello12234.3(12.3,32.8)
Run Code Online (Sandbox Code Playgroud)
我想在输出中添加换行符.但是,我找不到一个好方法,到目前为止我找到的最好的方法:
template<typename ... Args>
void print(Args ... args)
{
(cout << ... << ((std::ostringstream{} << args << "\n").str()));
}
Run Code Online (Sandbox Code Playgroud)
然而,这不是零开销,因为它ostringstream为每个参数构造临时值.
以下版本也不起作用:
(cout << ... << " " << args);
error: expression not permitted as operand of fold expression
Run Code Online (Sandbox Code Playgroud)
和
(cout << ... << (" " << args));
error: invalid operands to binary expression
Run Code Online (Sandbox Code Playgroud)
我理解为什么最后两个版本不起作用.使用折叠表达式是否有更优雅的解决方案?
我有一个函数采用可变参数包,在开始我想检查所有元素比较相等.我可以以某种方式使用新的C++ 17折叠表达式来简洁地编写一个单行程序吗?我刚在想
template<typename... Args>
void func (Args... args)
{
ASSERT ((args == ...));
// more code here...
}
Run Code Online (Sandbox Code Playgroud)
但这不起作用,因为它编译为首先正确比较后两个参数的代码,然后将第三个参数与第一个比较的结果进行比较,这是一个bool.这种类型的折叠表达式可能具有哪些用例(类似args < ...)?有没有机会我可以避免编写专用的递归模板来执行此操作?
我有以下函数来计算平均值:
template<typename... Ts>
auto mean_of(const Ts... values)
{
return (... + values) / static_cast<double>(sizeof...(Ts));
}
Run Code Online (Sandbox Code Playgroud)
使用VS 2017 15.6.0预览3以下代码
std::cout << mean_of(1, 3);
Run Code Online (Sandbox Code Playgroud)
输出2.5.似乎MSVC将折叠表达式解释为1 + 3 / N而不是(1 + 3) / N.如果我在fold表达式周围添加额外的括号,结果是正确的.使用GCC不需要额外的括号.
这是MSVC中的错误还是我们需要额外的括号?
c++ language-lawyer variadic-templates fold-expression c++17
考虑一个例子:
#include <type_traits>
template <class... Ts>
decltype (auto) foo(Ts... ts) {
return (ts->x + ...);
}
struct X {
int x;
};
int main() {
X x1{1};
static_assert(std::is_reference_v<decltype(foo(&x1))>);
}
Run Code Online (Sandbox Code Playgroud)
decltype(auto)从带括号的左值推导出的,应根据[cl.type.simple] /4.4推导出左值参考.例如:
decltype(auto) foo(X *x) { // type of result == int&
return (x->x);
}
Run Code Online (Sandbox Code Playgroud)
但是snipped会触发static_assert.即使我们将表达式组合成额外的括号,例如:
return ((ts->x + ...));
Run Code Online (Sandbox Code Playgroud)
它不会改变效果.
标准中是否有一点可以防止将单个元素的折叠表达式推导到左值参考中?
编辑
作为Johannes Schaub的一个重点- litb clang实际上确实将代码的双parens版本解释为带括号的左值并推导出左值引用.在这种情况下,我会将其解释为gcc错误.然而,具有单parens版本的版本仍然存在问题.让我感到困惑的是,至少在多个元素的情况下,必须将版本转换为带括号的代码 - 以实现运算符优先级.例如:
(x + ...)*4 -> (x1 + x2)*4
Run Code Online (Sandbox Code Playgroud)
不一致的原因是什么?
c++ ×10
fold-expression ×10
c++17 ×9
templates ×4
c++11 ×1
c++14 ×1
clang ×1
compiler-bug ×1
decltype ×1