I would like to use composition and to write good forwarding methods for every possible overload (noexcept, const, volatile) using C++ capabilities.
The idea is to use traits in order to determine whether a method is declared {noexcept / const / volatile / etc.} and to behave accordingly.
Here is an example of what I would like to achieve :
struct User{
UsedObject& obj;
User(UsedObject& obj) : obj(obj) {}
FORWARD_METHOD(obj, get); //here is where the forwarding happens
};
struct UsedObject{
string m{"Hello\n"};
string& get(double d){
cout << "\tUsed :const not called...\n";
return m;
}
const string& get(double d) const{
cout << "\tUsed :const called...\n";
return m;
}
};
Here is what I have so far** :
// forward with noexcept attribute
// I'm not 100% sure about : std::declval<std::add_lvalue_reference<decltype(obj)>::type
template<typename... Args>
constexpr decltype(auto) get(Args && ... args)
noexcept(
noexcept(std::declval<std::add_lvalue_reference<decltype(obj)>::type>().get( std::forward<Args>(args)... ))
and
std::is_nothrow_move_constructible<decltype( std::declval<std::add_lvalue_reference<decltype(obj)>::type>().get( std::forward<Args>(args)... ) )>::value
)
{
cout << "const called...\n";
return obj.get(std::forward<Args>(args)...);
}
// forward with noexcept and const attributes
// I'm not sure that this one behave properly.
template<typename... Args>
constexpr decltype(auto) get(Args && ... args)
const noexcept(
noexcept(std::declval< std::add_const<decltype(obj) &>::type >().get( std::forward<Args>(args)... ))
and
std::is_nothrow_move_constructible<decltype( std::declval< std::add_const<decltype(obj) &>::type >().get( std::forward<Args>(args)... ) )>::value
)
{
cout << "const not called...\n";
using const_type = std::add_lvalue_reference<std::add_const<std::remove_reference<decltype(obj)>::type>::type>::type;
return const_cast<const_type>(obj).get(std::forward<Args>(args)...);
}
Please note that this question is different from the following one, because I know that we can use c++ traits in order to inspect an object interface : Composition: using traits to avoid forwarding functions?
** inspired by a thread of comments with @David Stone here : When should I use C++ private inheritance?.