gpt4 book ai didi

c++ - 对 operator= 使用通用引用而不是多个重载

转载 作者:行者123 更新时间:2023-12-01 14:18:16 24 4
gpt4 key购买 nike

有一个简单的包装结构

template<typename T>
struct named_value {
using type = T;
T value{};
string_view name = "unnamed_value";

constexpr explicit operator T&(){ return value; }
constexpr explicit operator T const&()const{ return value; }
constexpr explicit operator T &&()&&{ return std::move(value); }

template<typename U=T>
constexpr named_value& operator=(U&&v){ value = std::forward<U>(v); return *this; }

friend auto operator<<(std::ostream& os, named_value const& a) ->ostream&
{
return os<<a.name<<":"<<a.value;
}
};

在这里,我尝试对 operator= 使用通用引用,以减少重载(即 ref、rval ref、const ref)。这是正确的方法吗?

最佳答案

这是一个有问题的实现。问题是它可能会干扰常规分配。编译器为您生成 operator=(name_value const&v),它接受一个 const 引用。但是当源对象是非常量时,从模板特化生成的重载变得更好匹配。

比如这段代码

named_value<int> a;
a = a;

使用 GCC 产生这个错误

main.cpp: In instantiation of 'constexpr named_value<T>& named_value<T>::operator=(U&&) [with U = named_value<int>&; T = int]':
main.cpp:18:10: required from here
main.cpp:13:51: error: cannot convert 'named_value<int>' to 'int' in assignment
13 | constexpr named_value& operator=(U&&v){ value = std::forward<U>(v); return *this; }

你需要用 SFINAE 来对抗它。所以,如果我们说那些可能去编译器生成重载的东西应该被拒绝。然后……

template<typename U=T, std::enable_if_t< !std::is_convertible_v<U&&, named_value> , int> = 0>
constexpr named_value& operator=(U&&v){ value = std::forward<U>(v); return *this; }

或者,如果使用 C++20

template<typename U=T> requires (!std::convertible_to<U&&, named_value>)
constexpr named_value& operator=(U&&v){ value = std::forward<U>(v); return *this; }

您当然可以选择其他检查,例如 std::is_samestd::same_as,具体取决于您希望实现的确切语义。

关于c++ - 对 operator= 使用通用引用而不是多个重载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62385274/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com