Здравствуйте, Voivoid, Вы писали:
Как пользователю функции foo понять какие поля присутствуют в возвращаемом значении?
Даже если список возвращаемых значений (по смысловой нагрузке) очевиден из очевиден из названия функции, конкретное их обозначения может быть не очевидным.
Например: my_map.insert( value ) возвращает поля iterator + is_new или pointer + old_value_replaced ?
Имхо, лучше уж замусорить namespace, но обьявить возвращаемую структуру явно, чем заставлять пользователя копаться в коде фенкции.
Если имена полей возвращаемых структур стандартизированы в "code style", но разные функции возвращают разные наборы полей (очевидные, из назначения функции),
то стоит их перечислить в коде явно. Добро пожаловать в named_tuple.
| моя реализация |
| namespace named_tuples
{
#define NT_DEFINE_FIELD( T, x ) \
struct x ## _field { T x; NT_IMPL_OPERATOR_JOIN( x ## _field ) }; \
inline x ## _field x ( T&& arg ) { return x##_field { std::move(arg) }; };
#define NT_DEFINE_AUTO_FIELD( x ) \
template<typename T> struct x ## _field { T x; NT_IMPL_OPERATOR_JOIN( x ## _field <T> ) }; \
template<typename T> x ## _field<T> x ( T&& arg ) { return x##_field<T> { std::move(arg) }; };
#define NT_IMPL_OPERATOR_JOIN(Tleft) \
template<typename Tright> \
friend ::named_tuples::join_result<Tleft,Tright> operator & ( Tleft&& a1, Tright&& a2 ) \
{ return ::named_tuples::join_result<Tleft,Tright> ( std::move(a1), std::move(a2) ); }
template<typename T1, typename T2>
struct join_result : T1, T2
{
typedef join_result<T1,T2> my_type;
join_result( T1&&a1, T2&&a2)
: T1( std::move(a1)), T2(std::move(a2))
{}
join_result( join_result&& ) = default;
join_result( const join_result& ) = default;
NT_IMPL_OPERATOR_JOIN(my_type)
};
}
//
namespace my_fields
{
NT_DEFINE_FIELD( int , a ) // Если поле может быть только фиксированного типа
NT_DEFINE_FIELD( double , b )
NT_DEFINE_FIELD( float , c )
NT_DEFINE_AUTO_FIELD( x ) // Если тип не определен.
NT_DEFINE_AUTO_FIELD( y )
NT_DEFINE_AUTO_FIELD( z )
}
auto foo()
{
// ....
return my_fields::x(10)
& my_fields::y(20)
& my_fields::z(30)
& my_fields::a(40)
& my_fields::c(60)
;
}
...
auto xyz = foo();
assert( xyz.x==10 );
assert( xyz.y==20 );
assert( xyz.z==30 );
static_assert( (std::is_same_v<decltype(xyz.c), float> ), "check fixed type" );
static_assert( (std::is_same_v<decltype(xyz.x), decltype(10) > ), "check auto type" );
|
| |