Я пытаюсь реализовать что-то вроде Rust типа Result<T,E>
в C ++, который представляет собой объединение со значением T
или E
.
Некоторые из его конструкторов:
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)) {}
Он работает, как я ожидаю, для T
и E
, которые не являются ссылочными типами или указателями, но не компилируется, если какой-либо из базовых типов является ссылкой. Например:
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);
^
Я понимаю, что это из-за правил свертывания ссылок (& + && = &): если T
равно MyType&
, то T&
и T&&
оба равны MyType&
, следовательно, эти два конструктора имеют здесь такая же подпись.
Но есть ли какой-нибудь хороший способ преодолеть это и позволить T
быть ссылкой, но при этом иметь конструкторы const T&
и T&&
?