在尝试使用C++ 17折叠表达式时,我试图实现max sizeof,其中结果是最多sizeof的类型.我有一个使用变量和lambda的丑陋折叠版本,但我无法想到使用折叠表达式并std::max()获得相同结果的方法.
这是我的折叠版本:
template<typename... T>
constexpr size_t max_sizeof(){
size_t max=0;
auto update_max = [&max](const size_t& size) {if (max<size) max=size; };
(update_max(sizeof (T)), ...);
return max;
}
static_assert(max_sizeof<int, char, double, short>() == 8);
static_assert(max_sizeof<char, float>() == sizeof(float));
static_assert(max_sizeof<int, char>() == 4);
Run Code Online (Sandbox Code Playgroud)
我想用折叠表达式编写等效函数std::max().例如,对于3个元素,它应该扩展为
return std::max(sizeof (A), std::max(sizeof(B), sizeof (C)));
Run Code Online (Sandbox Code Playgroud)
有可能吗?
有没有任何具体的情况下,你不能正确地做std::conjunction/ std::disjunction和不使用更多的“根本”(即语言特性,而不是库功能)在折叠式&&/ ||?
例:
// func is enabled if all Ts... have the same type
template<typename T, typename... Ts>
std::enable_if_t<std::conjunction_v<std::is_same<T, Ts>...> >
func(T, Ts...) {
// TODO something to show
}
Run Code Online (Sandbox Code Playgroud)
与
// func is enabled if all Ts... have the same type
template<typename T, typename... Ts>
std::enable_if_t<(std::is_same<T, Ts> &&...)>
func(T, Ts...) {
// TODO something to show
}
Run Code Online (Sandbox Code Playgroud)
使用fold表达式的版本更简短,通常更易读(尽管对此可能有不同的看法)。因此,我不明白为什么将它与折叠表达式一起添加到库中。
如何使用 C++20 概念限制可变参数模板和折叠表达式中允许的类型?
例如,假设我想限制以下折叠表达式仅支持整数类型,我该怎么做?
#include <string>
#include <iostream>
#include <concepts>
using namespace std;
template<typename... Args> // requires (is_integral<Args>::value )
int sum(Args... args) { return (... + args); }
int main()
{
cout << sum(1,2,3);
}
Run Code Online (Sandbox Code Playgroud) 当我发现以下可编译gcc但不编译的代码时,我正在尝试在折叠表达式中使用任意函数clang。
enum Enum {
A = 3,
B = 8,
C = 5
};
namespace EnumMax {
constexpr Enum operator>>=(const Enum left, const Enum right) {
return left < right ? right : left;
}
}
template<Enum ... enums>
constexpr Enum max() {
using EnumMax::operator>>=;
return (enums >>= ...);
}
constexpr Enum max_v = max<A, B, C>();
Run Code Online (Sandbox Code Playgroud)
似乎clang不考虑重载运算符,而是尝试>>=在fold表达式中使用正则运算符。
但是,如果改写了fold表达式,clang则考虑重载运算符,并且可以正常编译:
constexpr Enum maxExplicit() {
using EnumMax::operator>>=;
return (A >>= (B …Run Code Online (Sandbox Code Playgroud) 这段代码多次调用&foo :: next
struct foo
{
foo& next()
{
return *this;
}
};
template<typename Obj>
void tmp_funct_1(Obj& obj)
{}
template<typename Obj, typename Func, typename... Other>
void tmp_funct_1(Obj& obj, Func func, Other... other)
{
tmp_funct_1((obj.*func)(), other...);
}
Run Code Online (Sandbox Code Playgroud)
现在我想用一个折叠表达式替换递归调用
例:
template<typename Obj, typename... Func>
void tmp_funct_2(Obj& obj, Func... func)
{
(obj .* ... .* func());
}
Run Code Online (Sandbox Code Playgroud)
它不会编译,因为指向成员调用的指针的正确语法是
(obj.*func)()
Run Code Online (Sandbox Code Playgroud)
如何使用模板折叠表达式获得相同的结果?谢谢!
int main()
{
foo obj;
auto to_foo = &foo::next;
tmp_funct_1(obj, to_foo, to_foo, to_foo);
// tmp_funct_2(obj, to_foo, to_foo, to_foo);
}
Run Code Online (Sandbox Code Playgroud) 是的,我可以使用std::initializer_list.是的,更简单,我可以进行聚合初始化.但这是如何工作的?我似乎无法克服C++ 17的折叠表达式.那里没有足够的例子.
这是我想出的:
template<class T, std::size_t N>
struct foo
{
T arr[N];
template<typename... Args>
constexpr foo(Args&&... pack)
{
static_assert(sizeof...(pack) <= N, "Too many args");
std::size_t i = 0;
(arr[i++] = ...);
}
};
int main()
{
foo<int, 5> a(1, 2, 3, 4, 5);
}
Run Code Online (Sandbox Code Playgroud)
编辑:与最新的Clang编译.支持折叠表达式.
根据N4295, C++ 17将允许我计算未知数量的参数的总和,从而:
template<typename ... T>
int sum(T...t)
{
return (... + t);
}
Run Code Online (Sandbox Code Playgroud)
该文档进一步指出我可以使用诸如==或>之类的运算符而不是+.任何人都能想出一个合理的例子,当我想在这样的结构中使用==或>时?
(我意识到人们可以定义==和>为奇怪的课程做一些奇怪的事情,但肯定会违反良好的做法.写作a > b > c > d几乎不是一个好主意,是吗?)
template<class Msg, class... Args>
std::wstring descf(Msg, Args&&... args) {
std::wostringstream woss;
owss << Msg << ". " << ... << " " << args << ": '" << args << "' ";//not legal at all
//or
owss << Msg << ". " << args[0] << ": '" << args[1] << "' " << args[2] << ": '" << args[3] << "' "; //... pseudo code, and so on...
}
Run Code Online (Sandbox Code Playgroud)
我知道我可以只使用对列表或类似的东西,但我对如何做到这一点很感兴趣,同时保持函数的语法为:
const auto formatted = descf(L"message", "arg1", arg1, "arg2", arg2);
Run Code Online (Sandbox Code Playgroud) 我试过的编译器都没有接受这样的代码:
template <int ...a> bool foo() { return (a<=> ... <=>0); }
但对于任何其他<=,>=,==,!=,<,>它编译。
cppreference在这里很清楚 -<=>我们可以用于折叠表达式的二元运算符列表中没有。
这是 C++ 标准中的故意遗漏,还是编译器没有准备好?
这个问题只是纯粹的好奇;我只是想知道这方面的 C++ 方向是什么。我可以想象所有其他比较运算符将从允许的运算符的折叠表达式列表中删除,因为它们与<=>折叠表达式一样有意义......
c++ language-lawyer spaceship-operator fold-expression c++20
请考虑以下最小示例:
#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().
混合折叠表达式和空参数包时,预期的行为是什么?