#include <type_traits>
template<typename...Types> struct type_collection
{
public:
template<typename Type> struct collection_element
{
private:
template<typename DoesHave, typename T, typename...Rest>
static constexpr bool hasType()
{
return std::is_same<DoesHave, T>::value?true:
sizeof...(Rest)==0?false:
hasType<DoesHave, Rest...>();
}
public:
static_assert(hasType<Type, Types...>(), "No such type in the collection");
};
};
struct TypeA {};
struct TypeB {};
struct TypeC {};
int main()
{
using check1 = type_collection<TypeA, TypeB>::collection_element<TypeA>;
using check2 = type_collection<TypeA, TypeB>::collection_element<TypeC>;
check1 c1;
check2 c2;
}
Kod jest pewnie zdrowo schrzaniony.
Moja intecja jest taka: type_collection<TypeA, TypeB>::collection_element<TypeA>
powinno się kompilować, bo TypeA
jest w kolekcji, zaś type_collection<TypeA, TypeB>::collection_element<TypeC>
już nie (bo TypeC
nie jest wśród TypeA, TypeB
).
To sprawdzanie odbywa się przez funkcję hasType<Type, Types...>()
. Funkcja ma rekurencyjnie sprawdzać, czy argument Type
znajduje się wśród argumentów Types...
, za każdym wywołaniem porównując Type
z pierwszym spośród Types...
i wywołując się rekurencyjnie z Types...
okrojonymi o pierwszy argument.
Nie kompiluje się. I niestety, nie wiem, jak to poprawić. Mógłby ktoś coś poradzić? Dzięki!
wtf.cc:14:11: error: use of undeclared identifier 'hasType'
hasType<DoesHave, Rest...>();
^
wtf.cc:14:11: note: in instantiation of function template specialization
'type_collection<TypeA, TypeB>::collection_element<TypeA>::hasType<TypeA,
TypeB>' requested here
hasType<DoesHave, Rest...>();
^
wtf.cc:18:23: note: in instantiation of function template specialization
'type_collection<TypeA, TypeB>::collection_element<TypeA>::hasType<TypeA,
TypeA, TypeB>' requested here
static_assert(hasType<Type, Types...>(), "No such type in the co...
^
wtf.cc:31:10: note: in instantiation of template class 'type_collection<TypeA,
TypeB>::collection_element<TypeA>' requested here
check1 c1;
^
wtf.cc:10:31: note: must qualify identifier to find this declaration in
dependent base class
static constexpr bool hasType()
^
wtf.cc:14:11: error: no matching function for call to 'hasType'
hasType<DoesHave, Rest...>();
^~~~~~~~~~~~~~~~~~~~~~~~~~
wtf.cc:10:31: note: candidate template ignored: couldn't infer template argument
'T'
static constexpr bool hasType()
^
wtf.cc:14:11: error: no matching function for call to 'hasType'
hasType<DoesHave, Rest...>();
^~~~~~~~~~~~~~~~~~~~~~~~~~
wtf.cc:10:31: note: candidate template ignored: couldn't infer template argument
'T'
static constexpr bool hasType()
^
wtf.cc:14:11: error: use of undeclared identifier 'hasType'
hasType<DoesHave, Rest...>();
^
wtf.cc:14:11: note: in instantiation of function template specialization
'type_collection<TypeA, TypeB>::collection_element<TypeC>::hasType<TypeC,
TypeB>' requested here
hasType<DoesHave, Rest...>();
^
wtf.cc:18:23: note: in instantiation of function template specialization
'type_collection<TypeA, TypeB>::collection_element<TypeC>::hasType<TypeC,
TypeA, TypeB>' requested here
static_assert(hasType<Type, Types...>(), "No such type in the co...
^
wtf.cc:32:10: note: in instantiation of template class 'type_collection<TypeA,
TypeB>::collection_element<TypeC>' requested here
check2 c2;
^
wtf.cc:10:31: note: must qualify identifier to find this declaration in
dependent base class
static constexpr bool hasType()
^
wtf.cc:14:11: error: no matching function for call to 'hasType'
hasType<DoesHave, Rest...>();
^~~~~~~~~~~~~~~~~~~~~~~~~~
wtf.cc:10:31: note: candidate template ignored: couldn't infer template argument
'T'
static constexpr bool hasType()
^
wtf.cc:14:11: error: no matching function for call to 'hasType'
hasType<DoesHave, Rest...>();
^~~~~~~~~~~~~~~~~~~~~~~~~~
wtf.cc:10:31: note: candidate template ignored: couldn't infer template argument
'T'
static constexpr bool hasType()
^
wtf.cc:18:23: error: static_assert expression is not an integral constant
expression
static_assert(hasType<Type, Types...>(), "No such type in the co...
^~~~~~~~~~~~~~~~~~~~~~~~~
wtf.cc:32:10: note: in instantiation of template class 'type_collection<TypeA,
TypeB>::collection_element<TypeC>' requested here
check2 c2;
^
7 errors generated.