如何避免这种重复
How to avoid this kind of repetition
我有类似的代码:
#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() 函数中的代码重复?
替代 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
引用。
如果您需要在 get_def_impl
中访问 this
的成员,请使用 self.member
。
此外,您可以使用 std::conditional
或 get_def_impl
中的类似工具来根据 TSelf
的 const
-ness 做不同的事情。您还可以使用转发参考 (TSelf&&
) 并处理由于 ref-qualifiers and perfect-forwarding.
而移动 this
的情况
不直接回答问题,但我通常倾向于 const getter + non const setter - 这样你的 class 会在字符串出现时得到通知已更改并可以在需要时(将来)对其采取行动 - 无需遍历和更改使用它的所有内容。
在某些用例中,您还可以使用非成员函数模板,例如:
#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));
}
我有类似的代码:
#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() 函数中的代码重复?
替代 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
引用。
如果您需要在 get_def_impl
中访问 this
的成员,请使用 self.member
。
此外,您可以使用 std::conditional
或 get_def_impl
中的类似工具来根据 TSelf
的 const
-ness 做不同的事情。您还可以使用转发参考 (TSelf&&
) 并处理由于 ref-qualifiers and perfect-forwarding.
this
的情况
不直接回答问题,但我通常倾向于 const getter + non const setter - 这样你的 class 会在字符串出现时得到通知已更改并可以在需要时(将来)对其采取行动 - 无需遍历和更改使用它的所有内容。
在某些用例中,您还可以使用非成员函数模板,例如:
#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));
}