Reputation: 2684
I am implementing a type extractor extract_type<Class, nth-type>
for any templated class. An example usage is shown as follows:
template <int, short, float, double, char> class C;
extract_type<C, 0>::type => int
extract_type<C, 1>::type => short
extract_type<C, 2>::type => float
extract_type<C, 3>::type => double
extract_type<C, 4>::type => char
Here is my implementation.
// extract_type: recursive definition.
template <template <typename...> class C, size_t idx, typename T, typename... RestT>
struct extract_type;
// extract_type: base
template <template <typename...> class C, typename T, typename... RestT>
struct extract_type< C<RestT...>, 0, RestT... > {
using type = T;
};
// extract_type: recursive definition.
template <template <typename...> class C, size_t idx, typename T, typename... RestT>
struct extract_type : public extract_type< C<RestT...>, idx-1, RestT... > {
};
However, the compiler complains about
type/value mismatch at argument 1 in template parameter list for 'template class C, long unsigned int idx, class T, class ... RestT> struct OpenCluster::extract_type' struct extract_type< void, 0, RestT...>
How can I get this resolved?
Upvotes: 1
Views: 1020
Reputation: 1629
Here is my implementation.
#include "iostream"
template<class ...Ts> struct C {};
template<int N, class ...Ts>
struct extract_type_impl;
template<class C, int N>
struct extract_type;
template<template<class ...> class C, class ...Ts, int N>
struct extract_type<C<Ts...>, N> {
typedef typename extract_type_impl<N, Ts...>::type type;
};
template<int N, class T, class ...Ts>
struct extract_type_impl<N, T, Ts...> {
typedef typename extract_type_impl<N - 1, Ts...>::type type;
};
template<class T, class ...Ts>
struct extract_type_impl<0, T, Ts...> {
typedef T type;
};
int main() {
static_assert(std::is_same<extract_type<C<int, float, char, double>, 3>::type, double>::value, "");
// static_assert(std::is_same<extract_type<C<int, float, char, double>, 3>::type, int>::value, "");
}
Upvotes: -1
Reputation: 50540
Do you mean something like that (minimal, working example)?
#include<tuple>
#include<iostream>
#include<type_traits>
template<int, typename...>
struct extract_type;
template<int N, typename T, typename... O, template<typename...> typename U>
struct extract_type<N, U<T, O...>>: extract_type<N-1, U<O...>> { };
template<typename T, typename... O, template<typename...> typename U>
struct extract_type<0, U<T, O...>> { using type = T; };
int main() {
using MyTuple = std::tuple<int, double, char>;
// true
std::cout << std::is_same<extract_type<1, MyTuple>::type, double>::value << std::endl;
// false
std::cout << std::is_same<extract_type<2, MyTuple>::type, double>::value << std::endl;
}
This one would be your code (fixed and working version) instead:
#include<tuple>
#include<iostream>
#include<type_traits>
// extract_type: recursive definition.
template <template <typename...> class C, size_t idx, typename T, typename... RestT>
struct extract_type;
// extract_type: base
template <template <typename...> class C, typename T, typename... RestT>
struct extract_type< C, 0, T, RestT... > {
using type = T;
};
// extract_type: recursive definition.
template <template <typename...> class C, size_t idx, typename T, typename... RestT>
struct extract_type : public extract_type< C, idx-1, RestT... > { };
int main() {
// true
std::cout << std::is_same<extract_type<std::tuple, 1, int, double, char>::type, double>::value << std::endl;
// false
std::cout << std::is_same<extract_type<std::tuple, 2, int, double, char>::type, double>::value << std::endl;
}
Pretty ugly, isn't it?
The problem is that you define it as if to pass the template class separated from its parameters, so that the former has no role within extract_type
.
It means that you could have defined it as:
template <size_t idx, typename T, typename... RestT>
struct extract_type;
So, it would have been used as:
extract_type<1, int, double, char>::type
With the same result: double
.
Got the error in your example (apart the syntactic one, of course)?
Upvotes: 1