我正在尝试编写一个函数,它以std::tuple的形式返回变量参数包的子集。理想情况下,该函数应该没有运行时开销(没有不必要的副本),并且应该允许用户访问和修改lvalue引用。
应该维护值类型、lvalue引用和const lvalue引用。临时引用(rvalue引用),应该“转换”为值类型,以避免创建无效的引用(对临时引用)。
预期结果实例:
int lr = 5;
const int& clr = lr;
auto t = make_subpack_tuple(lr, clr, 5);
static_assert(is_same
<
decltype(t),
std::tuple<int&, const int&, int>
>{}, "");
// Ok, modifies lr:
std::get<0>(t) = 10;
// Compile-time error, intended:
// std::get<1>(t) = 20;
// Ok, 5 was moved into the tuple:
std::get<2>(t) = 30;不完全实施实例:
template<typename... Ts>
auto make_subpack_tuple(Ts&&... xs)
{
return std::tuple
<
some_type_trait<decltype(xs)>...
>
(
std::forward<decltype(xs)>(xs)...
);
}我想做的事有意义吗?
是否有一种标准的类型特征可以代替some_type_trait?还是我应该实施我自己的解决方案?
发布于 2015-10-29 18:38:42
你的解决办法是
template<typename... Ts>
auto make_subpack_tuple(Ts&&... xs)
{
return std::tuple<Ts...>(std::forward<Ts>(xs)...);
}根据模板参数演绎规则,参数pack Ts...将只包含cv限定的类型和值.这个问题中的信息也可能很有用。
发布于 2017-03-03 20:08:12
我只是想说明一下,在实现高效版本的Op时,我遇到了同样的问题(“我认为我需要衰减rvalue引用,保持lvalue引用不受影响”)。我曾经有过这样的混乱:
template<class Pack, class Op>
struct Foldable
{
mystery_trait_t<Pack> value;
const Op& op;
template<class RhsPack>
auto operator*(const Foldable<RhsPack, Op>& rhs) const {
return op(static_cast<std::decay_t<Pack>>(
(op.f)(std::move(value), std::move(rhs.value))
));
}
operator mystery_trait_t<Pack> () && {
return std::move(value);
}
};
template<class Pack>
auto NamedOperator::operator()(Pack&& value) const {
return Foldable<Pack, NamedOperator>(std::forward<Pack>(value), *this);
}然后(经过一段时间的困惑,然后开始问一个SO问题,并找到这个现有的问题/答案,并在我的mystery_trait_t实现中添加一个mystery_trait_t,以验证它从未使用rvalue引用类型被实际调用!)结果发现我真正需要的是
template<class Pack, class Op>
struct Foldable
{
Pack value;
const Op& op;
template<class RhsPack>
auto operator*(const Foldable<RhsPack, Op>& rhs) const {
return op(
(op.f)(std::move(value), std::move(rhs.value))
);
}
operator Pack () && {
return std::move(value);
}
};(请看我在Wandbox上的全部代码。)
我的这个“答案”并没有提供任何新的信息,但我认为分享它将是有用的,因为它只是表明,即使您认为您在模板元编程中非常深入,并且确信您需要这种“条件衰减”行为.你真的不需要它!
在维托里奥最初提出的问题中,他实际上做到了两次,尽管这两次都被decltype语法所掩盖,但这可能是一条必然的一般规则,即始终是一种代码味。
some_type_trait<decltype(xs)>... // should have been `Ts...`
std::forward<decltype(xs)>(xs)... // could equally well be `std::forward<Ts>(xs)...`https://stackoverflow.com/questions/33421323
复制相似问题