如何避免这种重复

时间:2016-09-30 09:11:31

标签: c++ c++11 dry

我的代码类似于:

#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";
};

我想知道是否有简单的方法来避免get()函数中的代码重复?

3 个答案:

答案 0 :(得分:13)

wandbox example

const_cast的替代方案:创建static模板函数,以*this作为参考:

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

这可以使用template argument deduction rules - 简而言之,TSelf会接受const和非const引用。

如果您需要访问this内的get_def_impl成员,请使用self.member

此外,您可以使用std::conditional内的get_def_impl或类似设施执行不同的操作,具体取决于const的{​​{1}}。您还可以使用转发引用TSelf,并处理ref-qualifiersperfect-forwarding移动TSelf&&的情况。

答案 1 :(得分:1)

在某些用例中,您还可以使用非成员函数模板,如:

#include <type_traits>
#include <string>

template <class U, class R = std::conditional_t<std::is_const<U>::value, std::string const&, std::string& >>
R get(U &u) {
   return u.s;
}

template <class U, class R = std::conditional_t<std::is_const<U>::value, std::string const&, std::string& >>
R get_def(U &u, typename std::remove_reference<R>::type& def) {
   return u.s.empty() ? u.s : def;
}

struct S {
   template <class U, class R>
   friend R get(U &);
   template <class U, class R>
   friend R get_def(U &, typename std::remove_reference<R>::type&);
private:
   std::string s;
};

int main() {
   S s;
   get(s) = "abc";
   //get(static_cast<const S &>(s)) = "abc"; // error: passing ‘const std::basic_string<char>’ as ‘this’...
   std::string s2 = get(static_cast<const S&>(s));
}

答案 2 :(得分:0)

不直接回答问题,但我通常倾向于使用const getter + non const setter - 这样,当字符串发生变化时,您的类会收到通知,如果需要,可以对其进行操作(将来) - 无需通过并更改使用它的所有内容。