Nick Nick - 2 months ago 12
C++ Question

How to avoid this kind of repetition

I have code similar to this:

#include <string>

class A{
public:
std::string &get(){
return s;
}

const std::string &get() const{
return s;
}

std::string &get_def(std::string &def){
return ! s.empty() ? s : def;
}

// I know this might return temporary
const std::string &get_def(const std::string &def) const{
return ! s.empty() ? s : def;
}

private:
std::string s = "Hello";
};


I am wondering is there easy way to avoid code repetition in get() functions?

Answer

wandbox example

Alternative to const_cast: creating a static template function that takes *this as a reference:

class A
{
private:
    template <typename TSelf, typename TStr>
    static auto& get_def_impl(TSelf& self, TStr& def)
    {
        return !self.s.empty() ? self.s : def;
    }

public:
    auto& get_def(std::string& str)
    {
        return get_def_impl(*this, str);
    }

    const auto& get_def(const std::string& str) const
    {
        return get_def_impl(*this, str);
    }
};

This works because of template argument deduction rules - in short, TSelf will accept both const and non-const references.

If you need to access members of this inside get_def_impl, use self.member.

Additionally, you can use std::conditional or similar facilities inside get_def_impl to do different things depending on the const-ness of TSelf. You can also use a forwarding reference (TSelf&&) and handle the case where this is being moved thanks to ref-qualifiers and perfect-forwarding.

Comments