NoS*_*tAl 24 c++ templates variadic-templates fold-expression c++17
在尝试使用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)
有可能吗?
Sto*_*ica 24
可能不是你想听到的,但没有.使用折叠表达式不可能(纯粹为1).他们的语法根本不允许它:
折叠表达式在二元运算符上执行模板参数包的折叠 .
Run Code Online (Sandbox Code Playgroud)fold-expression: ( cast-expression fold-operator ... ) ( ... fold-operator cast-expression ) ( cast-expression fold-operator ... fold-operator cast-expression ) fold-operator: one of + ??- ??* ??/ ??% ??^ ??& ??| ??<< ??>> +=??-=??*=??/=??%=??^=??&=??|=??<<=??>>=??= ==??!=??< ??> ??<=??>=??&&??||??, ??.* ??->*
仅仅因为函数调用表达式不是纯语法意义上的二元运算符.
1请参阅其他精湛的答案.
ild*_*arn 18
如果你想在这里使用fold表达式,那么你需要以某种方式使用运算符来调用std::max而不是函数调用.这是滥用operator^这个目的的一个例子:
namespace detail {
template<typename T, std::size_t N = sizeof(T)>
struct type_size : std::integral_constant<std::size_t, N> { };
template<typename T, auto M, typename U, auto N>
constexpr auto operator ^(type_size<T, M>, type_size<U, N>) noexcept {
return type_size<void, std::max(M, N)>{};
}
}
template<typename... T>
constexpr std::size_t max_sizeof() noexcept {
using detail::type_size;
return (type_size<T>{} ^ ... ^ type_size<void, 0>{});
// or, if you don't care to support empty packs
// return (type_size<T>{} ^ ...);
}
Run Code Online (Sandbox Code Playgroud)
编辑:@除去巴里的建议,T从type_size(改名为max_val这里):
namespace detail {
template<auto N>
struct max_val : std::integral_constant<decltype(N), N> { };
template<auto M, auto N, auto R = std::max(M, N)>
constexpr max_val<R> operator ^(max_val<M>, max_val<N>) noexcept {
return {};
}
}
template<typename... T>
constexpr std::size_t max_sizeof() noexcept {
using detail::max_val;
return (max_val<sizeof(T)>{} ^ ... ^ max_val<std::size_t{}>{});
// or, if you don't care to support empty packs
// return (max_val<sizeof(T)>{} ^ ...);
}
Run Code Online (Sandbox Code Playgroud)
在外部,两种实现都是等效的; 在实施方面,我个人更喜欢前者,但YMMV.: - ]
Bar*_*rry 18
既然没有人发布这个作为答案,那么用最小的努力做到这一点的最简单方法就是使用std::max()现成的重载来解决这个问题:一个需要initializer_list:
template<typename... T>
constexpr size_t max_sizeof() {
return std::max({sizeof(T)...});
}
Run Code Online (Sandbox Code Playgroud)
只是玩c ++ 17倍表达式
template <typename ... Ts>
constexpr std::size_t max_sizeof ()
{
std::size_t ret { 0 };
return ( (ret = (sizeof(Ts) > ret ? sizeof(Ts) : ret)), ... );
}
Run Code Online (Sandbox Code Playgroud)
或者,使用的事实std::max()被constexpr从C++ 14开始(因此它是在C++ 17)
template <typename ... Ts>
constexpr std::size_t max_sizeof ()
{
std::size_t ret { 0 };
return ( (ret = std::max(sizeof(Ts), ret)), ... );
}
Run Code Online (Sandbox Code Playgroud)
与您的原始版本没有太大区别.
| 归档时间: |
|
| 查看次数: |
3278 次 |
| 最近记录: |