如何覆盖 'const T&' 和 'T&&' 的泛型函数,其中 T 可以作为引用?

How to override generic function for aguments `const T&` and `T&&` where T could be a reference?

本文关键字:其中 函数 引用 何覆盖 覆盖 const 泛型      更新时间:2023-10-16

我正在尝试在 C++ 中实现类似 Rust 的 Result<T,E> 类型,这是一个持有TE值的联合。

它的一些构造函数是:

template <typename T, typename E>
Result<T,E>::Result(const T& value) : isOk(true), value(value) {}
template <typename T, typename E>
Result<T,E>::Result(T&& value) :  isOk(true), value(std::move(value)) {}

它按照我所期望的TE是非引用类型或指针工作,但如果任何基础类型是引用,则无法编译。例如:

MyType my_object;
Result<MyType&, AnyOtherType> result(my_object);

产生以下错误:

./result.h:46:5: error: multiple overloads of 'Result' instantiate to the same signature 'void (MyType &)'
    Result(T&& value);
    ^
main.cpp:39:23: note: in instantiation of template class 'Result<MyType &, int>' requested here
  Result<MyType&,int> result(object);
                      ^
./result.h:37:5: note: previous declaration is here
    Result(const T& value);
    ^

我知道这是因为引用折叠规则(&+ &&= &(:如果TMyType&,那么T&T&&都是MyType&,因此这两个构造函数在这里具有相同的签名。

但是有什么好方法可以克服这个问题,并允许T作为参考,同时仍然拥有const T&T&&构造函数?

可以使用带有转发引用的模板化构造函数来涵盖这两种情况:

template<typename T>
struct Result {
    template<typename... S>
    Result(S&&... s) : t(std::forward<S>(s)...) {}
    T t;
};
int i;
Result<int&> r1(i);
Result<int> r2(i);

关于std::expected<R, E>提案的相关文件:

  • http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4109.pdf
  • http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0323r7.html
相关文章: