I have a class inherited from standard tuple:
#include <concepts>
#include <cstdint>
#include <iostream>
#include <string>
#include <tuple>
#include <vector>
template< typename ... Args >
class Identifier: public std::tuple< Args... >
{
public:
Identifier( Args... args ) requires( sizeof...( Args ) != 0 ) : std::tuple< Args... >( std::move( args )... )
{}
Identifier( std::tuple< Args... > tuple ):std::tuple< Args... >( tuple )
{}
Identifier()
{}
Identifier(std::convertible_to<std::tuple<Args...>> auto&& identifier)
: std::tuple<Args...>(std::forward<decltype(identifier)>(identifier)) {}
};
int main()
{
Identifier<std::wstring, std::int64_t> id(L"id", 10);
auto& [ str_id, num_id ] = id;
std::tuple< std::wstring, int64_t > tuple_id(L"id", 10);
auto& [ str_t_id, num_t_id ] = tuple_id;
return 0;
}
in line
auto& [ str_id, num_id ] = item;
I got error Type 'Identifier<std::wstring, int64_t>' (aka 'Identifier<basic_string<wchar_t>, long long>') decomposes into 1 element, but 2 names were provided
but the same code for tuple variable its ok
auto& [ str_t_id, num_t_id ] = tuple_id;
What I have to do to support structured binding for class Identifier ?
I have a class inherited from standard tuple:
#include <concepts>
#include <cstdint>
#include <iostream>
#include <string>
#include <tuple>
#include <vector>
template< typename ... Args >
class Identifier: public std::tuple< Args... >
{
public:
Identifier( Args... args ) requires( sizeof...( Args ) != 0 ) : std::tuple< Args... >( std::move( args )... )
{}
Identifier( std::tuple< Args... > tuple ):std::tuple< Args... >( tuple )
{}
Identifier()
{}
Identifier(std::convertible_to<std::tuple<Args...>> auto&& identifier)
: std::tuple<Args...>(std::forward<decltype(identifier)>(identifier)) {}
};
int main()
{
Identifier<std::wstring, std::int64_t> id(L"id", 10);
auto& [ str_id, num_id ] = id;
std::tuple< std::wstring, int64_t > tuple_id(L"id", 10);
auto& [ str_t_id, num_t_id ] = tuple_id;
return 0;
}
in line
auto& [ str_id, num_id ] = item;
I got error Type 'Identifier<std::wstring, int64_t>' (aka 'Identifier<basic_string<wchar_t>, long long>') decomposes into 1 element, but 2 names were provided
but the same code for tuple variable its ok
auto& [ str_t_id, num_t_id ] = tuple_id;
What I have to do to support structured binding for class Identifier ?
Share Improve this question edited Feb 17 at 21:51 Ted Lyngmo 117k7 gold badges82 silver badges132 bronze badges asked Feb 17 at 21:28 Vladimir ShttlVladimir Shttl 613 bronze badges 4 |3 Answers
Reset to default 0I can't see a direct duplicate for this, although there are overlapping questions on tuple-like binding protocol.
For this case (not an array, not a simple aggregate: specifically case 2 here),
- The expression
std::tuple_size<E>::value
must be a well-formed integral constant expression,
but it isn't. Having std::tuple_size<std::tuple<...>>
defined doesn't help a subclass, because implicit conversions don't happen here.
You'll need to specialize it yourself.
- For each structured binding, a variable whose type is "reference to
std::tuple_element<I, E>::type
" is introduced:...
You'll need to specialize this too. They can both just forward to the std::tuple
versions.
You also need
e.get<I>()
, if lookup for the identifierget
in the scope ofE
by class member access lookup finds at least one declaration ...- Otherwise,
get<I>(e)
, where get is looked up by argument-dependent lookup only, ignoring non-ADL lookup.
But here we finally have ADL doing the work of finding the normal std::get
for us.
Structured binding won't work with std::tuple
and a template parameter pack
You need to specialize std::tuple
and implement tuple_size
and tuple_element
Examples here: Direct initialization fails with class derived from std::tuple, while it works for std::pair
Implemented the classes tuple_size and tuple_element and it worked
template < class... Args >
struct std::tuple_size< sbis::IdentifierType< Args...> > : public std::integral_constant< size_t, sizeof...( Args ) > {};
template< std::size_t I, class... Args >
class std::tuple_element< I, sbis::IdentifierType< Args... > > : public tuple_element< I, std::tuple< Args... > >{};
item
you meanid
, right? It's helpful to be certain the error matches the code exactly. – Useless Commented Feb 17 at 21:57return 0
, it was fine without. Just FYI) – Useless Commented Feb 17 at 21:58