我相信我理解C++中完美转发的概念。但我错过了“这个”类似的东西。让我们:
class X {
std::vector<int> vec;
public:
std::vector<int> const &getVec() const & { return vec; }
std::vector<int> & getVec() & { return vec; }
std::vector<int> getVec() && { return std::move(vec); }
};
由于 std::forward()
压缩参数的类似定义,我希望有类似的“this”。像这样的东西:
class X {
std::vector<int> vec;
public:
auto &&getVec() /*???const &*/ { return thisForward(vec); }
};
类似上面的东西可能吗(或者在STL或boost中可用)?或者,至少有一些解决方法吗?
再加一个问题(仅用于验证),上面的 getVec()
的 3 个重载有意义吗?有这样 3 个重载可以吗(出于优化原因)? (假设“X”是一个类似容器的类。)
最佳答案
对于 C++20,您可以接近,但我不知道如何完全按照您的要求进行操作。
如果你愿意转get
进入静态/友元函数,它可以工作。我无法将辅助类型的重复次数减少到零,但也许可以改进。如果您愿意向引用成员付费,这可能可以通过包装器来实现,但该包装器必须存储对该成员的引用。
#pragma once
#include <type_traits>
template <typename T>
concept lvalue = std::is_lvalue_reference_v<T> && !std::is_const_v<std::remove_reference_t<T>>;
template <typename T>
concept lcvalue = std::is_lvalue_reference_v<T> && std::is_const_v<std::remove_reference_t<T>>;
template <typename T, typename R>
struct RT {
using type = R;
};
template <lvalue T, typename R>
struct RT<T,R> {
using type = std::add_lvalue_reference_t<std::remove_const_t<R>>;
};
template <lcvalue T, typename R>
struct RT<T,R> {
using type = std::add_lvalue_reference_t<std::add_const_t<R>>;
};
template <typename T, typename R>
using RT_t = typename RT<T,R>::type;
示例:
#include <vector>
#include <cassert>
#include "rt.h"
namespace {
struct X {
std::vector<int> v;
template <typename Self>
friend RT_t<Self,std::vector<int>> get(Self&& self) {
return std::forward<RT_t<Self,std::vector<int>>>(self.v);
}
};
}
int main() {
X x{std::vector{1,2,3}};
assert(x.v.size() == 3);
X& xr = x;
get(xr).push_back(1);
assert(x.v.size() == 4);
//X const& xc = x;
//get(xc).push_back(1); // does not compile
{
std::vector<int> vec = get(std::move(x));
assert(vec.size() == 4);
}
assert(x.v.size() == 0);
}
所以,缺点:
- 必须写
get(x)
而不是x.get()
- 定义
get
时必须重复RT_t<Self,std::vector<int>>
关于c++ - 缺少像 std::forward 这样的东西,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73689241/