Automaticly add CV-qualified functions

佐手、 提交于 2019-12-11 00:09:15

问题


I have next class

class Parameter
{
private:
    T value_;

public:
    // Get
    T& value()                                 { return value_; }
    volatile T& value() volatile               { return value_; }
    const T& value() const                     { return value_; }
    const volatile T& value() volatile const   { return value_; }
}

How can I minimize number of lines, amount of code. I want to write once T& value() and achieve CV-qualified versions automatically. Possible?


回答1:


Yes, you could use macro, but I can't see any use of such:

#define IDK_WHY(returnType, functionName, functionArgs, functionBody) \
                   returnType functionName functionArgs                functionBody \
    volatile       returnType functionName functionArgs volatile       functionBody \
    const          returnType functionName functionArgs const          functionBody \
    const volatile returnType functionName functionArgs volatile const functionBody

class Parameter
{
    using T = int; //for testing, dunno what is T in your code
private:
    T value_;

public:
    // note you can't use comma in last argument, it would require more complex macro
    IDK_WHY(T&, value, (), { return value_;}) //done
};



回答2:


If you are going to expose every reference to a variable, expose the variable.

Now p.value_ does exactly what you want.

Barring that, the easiest way is to write:

template< class A, class B >
using same_test = std::enable_if_t< std::is_same< std::decay_t<A>, std::decay_t<B> >{}, int>

then inside the class write:

template<class Self, same_test<Self, Parameter> =0>
friend decltype(auto) get_value( Self&& self ) {
  return decltype(self)(self).value_;
}

now get_value( p ) will return p.value with the right l/r/cv qualifications.

If you don't like that syntax, I can provide you with (p->*value)():

template<class F>
struct magic_method_ptr_t {
  F f;
  template<class Lhs>
  friend auto operator->*(Lhs&& lhs, magic_method const& m) {
    return [&](auto&&...args)->decltype(auto) {
      return m.f( decltype(lhs)(lhs), decltype(args)(args)... );
    };
  }
};
template<class F>
magic_method_ptr_t<F> magic_method_ptr( F f ) { return {std::move(f)}; }

auto value = magic_method_ptr( [](auto&& x){ return get_value(decltype(x)(x)); }

Add this to the get_value case above, and (p->*value)() works.

I cannot provide you with p.value() syntax, barring ugly macros.




回答3:


Another solution could be with the usage of macros. Maybe is less elegant, but it's very simple, clear and powerful.

You may define a macro simply taking the member variable name and writing each getter (you can explode that with setter and other utilities as well).

/// @param X is the variable name
/// @param Y is the get name. The result will be get_##Y
#define create_getters(X, Y) decltype(X)& get_##Y() {   \
    return this->X; \
  } \
  const decltype(X)& get_##Y() const { \
    return this->X; \
  }

// Example class
class Foo {
  std::string m_data;

 public:
  // expose m_data as get_Data()
  create_getters(m_data, Data);  // Actually you don't need ; here
};

int main(int argc, char *argv[]) {
  Foo f;
  auto&& r = f.get_Data();  // ref
  auto&& cr = static_cast<const Foo&>(f).get_Data();  // const-ref

  return 0;
}


来源:https://stackoverflow.com/questions/39498501/automaticly-add-cv-qualified-functions

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!