Как правильно "совершенствовать вперед" функции геттера?

Я создаю библиотеку JSON для С++ 14, и я стараюсь использовать семантику перемещения, когда это возможно.

В моем классе Value есть несколько сеттеров и геттеров, которые всегда стараются двигаться, когда это возможно:

template<class T> void setObj(T&& x)  { type = Obj; hObj.init(forward<T>(x)); } 
template<class T> void setArr(T&& x)  { type = Arr; hArr.init(forward<T>(x)); }
template<class T> void setStr(T&& x)  { type = Str; hStr.init(forward<T>(x)); }

auto& getObj() & noexcept             { assert(is<Obj>()); return hObj; }
auto& getArr() & noexcept             { assert(is<Arr>()); return hArr; }
auto& getStr() & noexcept             { assert(is<Str>()); return hStr; }
const auto& getObj() const& noexcept  { assert(is<Obj>()); return hObj; }
const auto& getArr() const& noexcept  { assert(is<Arr>()); return hArr; }
const auto& getStr() const& noexcept  { assert(is<Str>()); return hStr; }
auto getObj() && noexcept             { assert(is<Obj>()); return move(hObj); }
auto getArr() && noexcept             { assert(is<Arr>()); return move(hArr); }
auto getStr() && noexcept             { assert(is<Str>()); return move(hStr); }

Как вы можете видеть из кода, отличные функции настройки пересылки довольно легко использовать с шаблонами и универсальными ссылками.

Как я могу сделать то же самое для функций getter? Я уверен, что мне нужно использовать тип возвращаемого шаблона, но я не уверен, как реплицировать ref-qualifiers и const-correctness.

Ответы

Ответ 1

Так как вы не можете создавать шаблоны для спецификаторов ref и константы членов, грустный ответ заключается в том, что вы не можете. Вы должны написать их.

Ответ 2

Это не похоже на шаблоны С++, но он выполняет эту работу.

    #define GETTERS(V) \
            V(Obj) \
            V(Arr) \
            V(Str)

    #define VISIT(X) \
            auto &get ## X() & noexcept { assert(is<X>()); return h ## Obj; } \
            const auto &get ## X() const& noexcept { assert(is<X>()); return h ## Obj; } \
            auto &get ## X() && noexcept { assert(is<X>()); return std::move(h ## Obj); }


    GETTERS(VISIT)