问题
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