是否可以编写一个可以独占存储左值引用或对象的类?

问题描述 投票:0回答:1

我厌倦了按值传递所有对象,然后移动或重载左值和右值。我正在尝试编写一个类,如果将右值传递到构造函数中,则该类可以存储左值引用或普通对象。

这是骨架:

template<typename T>
class ref {
private:
    T* m_ptr = nullptr;
    std::optional<T> m_obj;
    bool is_lvalue = true;
public:
    ref(T& lvalue_ref) : m_ptr{ &lvalue_ref } {}
    ref(T&& rvalue_ref) : m_obj{ std::move(rvalue_ref) }, is_lvalue{ false } {}

    T& get() {
        return (is_lvalue) ? *m_ptr : *m_obj;
    }
};

我想将此类与

void foo(ref<bar> r) {}
等函数一起使用,因此任何采用
ref<T>
的函数都不会进行任何复制。不幸的是,每当你获取值时,你都必须检查是否存储了引用/对象,并且
std::optional
默认构造了它的对象,即使我们存储的是左值,我们也要为此付费。是否可以创建一个存储左值引用或对象的类,并且仍然能够有一个函数采用
ref<T>
能够将 T 的左值和右值绑定到它?

c++ reference rvalue-reference
1个回答
0
投票

我会先引用我的评论,以便大家可以全面了解我的...观点。

我同意@JaMiT,这是一个XY问题。事实上,这个问题的特点是一个没有明确定义的问题的可能解决方案的框架:你写“我厌倦了按值传递所有对象,然后移动或重载左值和右值”。如何?展示一个代码示例,让您认为您需要解决问题。您在右值引用和左值引用通用上下文上重载的上下文是吗?或者您指的是具有具体值的函数? Q 中没有解释这些方面。

但我仍然认为可以尝试一些猜测。

来自

我厌倦了按值传递所有对象,然后移动或重载左值和右值。

因为你有很多这样的代码示例(
int

可以是任何其他

具体类型
),我猜? // foo.hpp #pragma once void foo(int const&); void foo(int&&);

// foo.cpp
#include <iostream>
void foo(int&) {
    std::cout << "I'm for Lvalues" << std::endl;
}
void foo(int&&) {
    std::cout << "I'm for Rvalues" << std::endl;
}
// main.cpp#
include "foo.hpp"
int main()
{
    foo(3);
    int x{3};
    foo(x);
}
如果是这种情况,一种解决方案可能是仅对函数进行模板化并
在 cpp 文件中实现它们,

以及您需要的两个显式实例化 // foo.hpp #pragma once template<typename T> void foo(T&&);

// foo.cpp
template<typename T>
void foo(T&&) {
    if constexpr (std::is_lvalue_reference_v<T&&>) {
        std::cout << "I'm for Lvalues" << std::endl;
    } else {
        std::cout << "I'm for Rvalues" << std::endl;
    }
}

template void foo(int&);
template void foo(int&&);
请注意,我的玩具示例在两种情况下都具有相同的长度,但两者之间存在一些差异:

在我提出的解决方案中,
    只有一个
  • 为右值和左值共享实现,因此您不会重复业务逻辑, 在我提出的解决方案中,您可以仅将
  • std::forward<T>
  • 参数传递给其他函数,而在“手动”重载情况下,您必须在一个重载中编写
    std::move
    ,而在另一个重载中不编写任何内容。
    
        
© www.soinside.com 2019 - 2024. All rights reserved.