b00rt00s Temat założony przez niniejszego użytkownika |
[C++] klasy cech i i szablony jako parametry typu » 2016-11-09 16:41:06 Problem jest jak najbardziej wydumany, ale zależy mi na zrozumieniu pewnego mechanizmu. Oto program (z potrzebnymi komentarzami): #include <map> #include <set> #include <type_traits>
using namespace std;
template < typename T > struct traits_1;
template <> struct traits_1 < int > { template < typename...Args > using type = std::map < Args...>; };
template < template < class...> class _map_ > struct traits_2;
template <> struct traits_2 < std::map > { template < typename T > using container = std::set < T >; };
template < typename T > using container_type_1 = typename traits_2 < std::map >::container < T >;
template < typename...Args > using map_type = typename traits_1 < int >::template type < Args...>;
static_assert( std::is_same < map_type < int, int >, std::map < int, int >>::value, "typy sa inne" );
template < typename T > using container_type_2 = typename traits_2 < map_type >::container < T >;
int main( int argc, char * argv[] ) { container_type_1 < int > t1; container_type_2 < int > t2; return 0; } Oto błędy kompilacji z kompilatora clang: main.cpp:43:35: error: implicit instantiation of undefined template 'traits_2<map_type>' using container_type_2 = typename traits_2<map_type>::container<T>; ^ main.cpp:21:8: note: template is declared here struct traits_2; ^ main.cpp:43:55: error: expected a qualified name after 'typename' using container_type_2 = typename traits_2<map_type>::container<T>; ^ main.cpp:43:55: error: type-id cannot have a name using container_type_2 = typename traits_2<map_type>::container<T>; ^~~~~~~~~ main.cpp:43:64: error: expected ';' after alias declaration using container_type_2 = typename traits_2<map_type>::container<T>; ^ ; main.cpp:49:2: error: no template named 'container_type_2'; did you mean 'container_type_1'? container_type_2<int> t2; ^~~~~~~~~~~~~~~~ container_type_1 main.cpp:32:1: note: 'container_type_1' declared here using container_type_1 = typename traits_2<std::map>::container<T>; ^ main.cpp:46:14: warning: unused parameter 'argc' [-Wunused-parameter] int main(int argc, char *argv[]) ^ main.cpp:46:26: warning: unused parameter 'argv' [-Wunused-parameter] int main(int argc, char *argv[]) ^ 2 warnings and 5 errors generated. Pytanie brzmi, czemu ten kod kompiluje i jak można go naprawić? Mam wprawdzie swoje podejrzenia, ale nie mam pomysłu co z tym zrobić... |
|
Monika90 |
» 2016-11-09 17:08:45 map_type<K,V,C,A> to jest to samo co std::map<K,V,C,A>, ale map_type to nie jest to samo co std::map, są to dwa różne szablony. Można dodać specjalizację dla map_typetemplate <> struct traits_2 < map_type > { template < typename T > using container = std::set < T >; };
wtedy kod da się skompilować: http://coliru.stacked-crooked.com/a/0ab76a55cc00f5bd |
|
b00rt00s Temat założony przez niniejszego użytkownika |
» 2016-11-09 18:34:00 Tak, to prawda, ale wówczas cała zabawa z klasami cech traci sens. Moim zamysłem było, żeby z klasy traits_1 wydobyć typ szablonowy, który pozwoli wydobyć kolejny typ z klasy traits_2. Wyobraźmy sobie, że dodamy takie dwie specjalizacje: template <> struct traits_1 < std::string > { template < typename...Args > using type = std::multimap < Args...>; };
template <> struct traits_2 < std::multimap > { template < typename T > using container = std::multiset < T >; }; oraz gdzieś będziemy chcieli zdobyć wydobyć typ dla klasy std::string, wiec dodamy taki alias: template < typename...Args > using map_type_2 = typename traits_1 < std::string >::template type < Args...>; którego użylibyśmy tak: template < typename T > using container_type_3 = typename traits_2 < map_type_2 >::container < T >; Pytanie, czy takie coś jest w ogóle możliwe? Jakimś innym sposobem oczywiście ;) |
|
Monika90 |
» 2016-11-09 19:18:57 Nie wiem po co jest ten pośrednik map_type_2? A może tak? #include <map> #include <set> #include <string>
template < template < class...Args > class T > struct alias { template < class...Args > using type = T < Args...>; };
template < class > struct traits_1;
template <> struct traits_1 < std::string > { using type = alias < std::multimap >; };
template < class > struct traits_2;
template <> struct traits_2 < alias < std::multimap >> { template < class T > using container = std::multiset < T >; };
int main() { traits_2 < traits_1 < std::string >::type >::container < int > x; }
|
|
Monika90 |
» 2016-11-09 19:55:45 Albo tak? #include <map> #include <set> #include <string> #include <type_traits>
template < class > struct traits_1;
template <> struct traits_1 < std::string > { template < class...Args > using type = std::multimap < Args...>; };
template < template < class...> class, class = void > struct traits_2;
template < template < class...> class T > struct traits_2 < T, std::enable_if_t < std::is_same < std::multimap < int, int >, T < int, int >>::value >> { template < class U > using container = std::multiset < U >; };
int main() { traits_2 < traits_1 < std::string >::type >::container < int > x; }
|
|
b00rt00s Temat założony przez niniejszego użytkownika |
» 2016-11-21 17:39:31 Dzięki, te przykłady działają. |
|
« 1 » |