Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to correctly "perfect forward" getter functions?

I'm creating a JSON library for C++14 and I'm trying to make use of move semantics whenever possible.

My Value class has several setters and getters that always try to move when possible:

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); }

As you can see from the code, perfect forwarding setter functions is pretty easy using templates and universal references.

How can I do the same for getter functions? I'm pretty sure I have to use a template return type but I'm not sure how to replicate ref-qualifiers and const-correctness.

like image 639
Vittorio Romeo Avatar asked Sep 29 '14 10:09

Vittorio Romeo


2 Answers

Since you can't template on ref qualifiers and member constness, the sad answer is that you can't. You have to write them out.

like image 98
Sebastian Redl Avatar answered Oct 10 '22 17:10

Sebastian Redl


This is not like C++ templates but it does the job.

    #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)
like image 30
Alexander Oh Avatar answered Oct 10 '22 18:10

Alexander Oh