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

时间:2019-06-11 13:09:38

标签: c++ c++11 templates move-semantics rvalue-reference

我正在尝试在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&&都是{ {1}},因此这两个构造函数在此处具有相同的签名。

但是有什么好的方法可以克服这个问题,并允许MyType&作为引用,同时仍然具有Tconst T&构造函数?

1 个答案:

答案 0 :(得分:2)

您可以将模板构造函数与转发引用一起使用,以解决这两种情况:

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>提案的相关论文: