Вы можете отложить вычет типа its_i_type
. По сути, вы создаете простую оболочку, которую нужно пройти.
Чтобы распространить его на другие типы, которые вам нужны (я хотел предложить type_traits
-подобное решение, но поскольку вам не нужны специализации), вы можете определить все типы, которые вам нужны:
template<typename T>
struct Wrapper {
private:
template<typename U> struct i_typper { using type = typename U::i_type; };
template<typename U> struct k_typper { using type = typename U::k_type; };
template<typename U> struct p_typper { using type = typename U::p_type; };
public:
using i_trait = i_typper<T>;
using k_trait = k_typper<T>;
using p_trait = p_typper<T>;
};
Пример:
struct A { using i_type = int; };
struct B { using i_type = int; using k_type = float; };
int main() {
Wrapper<A> w; //Works now.
Wrapper<A>::i_trait::type mk1; //Works
Wrapper<A>::k_trait::type mk2; //Fails, not defined
Wrapper<B>::i_trait::type mk3; //Works
Wrapper<B>::k_trait::type mk4; //Works
}
В случае:
template<typename T>
struct Wrapper {
typename T::i_type call_f() { return 0; }
// does not compile, even if `call_f()` is never instantiated
};
Здесь у вас есть несколько вариантов:
- сделать эту функцию шаблоном функции-члена
- Используйте какую-то форму
type_traits
механизма, который все равно будет включать специализацию
- Пойдите путем абстрагирования общих
Wrapper
вещей в базовом классе WrapperBase
;
Для первого варианта вам придется немного изменить его, чтобы дополнительно отложить вычет
template<typename T>
struct Wrapper {
private:
template<typename U, typename> struct i_typper { using type = typename U::i_type; };
template<typename U, typename> struct k_typper { using type = typename U::k_type; };
template<typename U, typename> struct p_typper { using type = typename U::p_type; };
public:
using i_trait = i_typper<T, void>;
using k_trait = k_typper<T, void>;
using p_trait = p_typper<T, void>;
template<typename U = void>
typename k_typper<T, U>::type call_f() { return 0; }
};
Я оставлю второй вариант в качестве упражнения: (в итоге может получиться что-то вроде:
template<typename T>
struct wrapper_traits {
....
};
template<>
struct wrapper_traits<A>{
using ....
};
template<typename T>
struct Wrapper {
....
public:
using i_trait = wrapper_traits<T>;
using k_trait = wrapper_traits<T>;
using p_trait = wrapper_traits<T>;
};
Ответ Джарода проще. Но это сработает, если у вас нет доступа к std::experimental
или политика вашей компании запрещает вам ...
person
WhiZTiM
schedule
05.08.2016