首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >有没有可能在没有类型推断的情况下实现类似转发引用的行为?

有没有可能在没有类型推断的情况下实现类似转发引用的行为?
EN

Stack Overflow用户
提问于 2017-01-17 20:57:49
回答 1查看 221关注 0票数 4

最近,我了解了通用(或转发)引用。它们只适用于类型推导,如模板或auto / decltype

当我使用左值引用(&)时,我不能将它绑定到右值(临时)对象。当我使用一个右值引用(&&)时,我不能将它绑定到左值对象。转发引用可以与非常数左值和右值一起工作。

有没有可能在没有类型推断的情况下实现转发引用行为?

代码语言:javascript
运行
复制
void Foo(string && s); // rvalue-reference
void Bar(const string & s); // const lvalue-reference
void Baz(auto && s); // forwarding reference

string s = "lvalue string";

Foo(s);      // error: cannot bind lvalue to &&
Foo("test"); // OK

// works, but can't take non-const value
Bar(s);
Bar("test");

// works
Baz(s);
Baz("test");
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-01-17 23:09:52

说大也大吧。您可以键入擦除对T的前向引用的概念。

代码语言:javascript
运行
复制
template<class T>
struct forward_ref {
  using extract_sig = T(void*);
  using get_sig = T const&(void*);

  extract_sig* extract = nullptr;
  get_sig* gettor = nullptr;

  void* pvoid;


  template<class U>
  void wrap( U&& t ) {
    auto* pt = std::addressof(t);
    using pT = decltype(pt);
    pvoid = const_cast<void*>(static_cast<void const*>(pt));
    gettor = [](void* pvoid)->T const& {
      // std::cout << "getting:\n";
      auto* pt = static_cast<pT>(pvoid);
      return *pt;
    };
    extract = [](void* pvoid)->T {
      // std::cout << "extracting via " << (std::is_rvalue_reference<U&&>::value?"move":"copy") << "\n";
      auto* pt = static_cast<pT>(pvoid);
      return std::forward<U>(*pt);
    };
  }

  forward_ref(T const& t){ wrap(t); }
  forward_ref(T && t = {}){ wrap(std::move(t)); }


  bool valid() const { return gettor&&extract; }
  operator T()&&{
    // std::cout << "operator T&&\n";
    T r = extract(pvoid);
    // std::cout << "extracted\n";
    gettor=nullptr; extract=nullptr; pvoid=nullptr;
    return r;
  }
  operator T const&() const &{
    // std::cout << "operator T const&\n";
    return gettor(pvoid);
  }
  T get()&& { return std::move(*this); }
  T const& get() const& { return *this; }
};

所以你可以这样做:

代码语言:javascript
运行
复制
void Foo(forward_ref<std::string> s); // rvalue-reference

并且s的行为(在某种程度上)类似于对std::string的转发引用。

如果从s取值,它要么复制传入的std::string,要么根据它是右值还是左值而移动它。

现在,这是相当愚蠢的,因为

代码语言:javascript
运行
复制
void Foo(std::string s)

几乎总是比上面那个花哨的forward_ref更好的主意。

如果移动很便宜,并且你打算复制一份拷贝,那么按值取值几乎和转发引用一样快。

如果move不比copy便宜,那就用const&吧。

这是极其罕见的移动是昂贵的,而拷贝是更昂贵的。

转发引用很有用,因为在泛型代码中,您不知道移动是否很便宜。一种具体的类型你知道。

在任何情况下,该类型live example擦除前向引用。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41697851

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档