Consider a base template class and a derived template class in a heavy template metaprogramming context (simplified here for readability and to focus on the problem).
template <class T>
struct base {
using type = T;
static constexpr int value = 0;
template <class... Args>
constexpr void function(Args&&...) {}
template <class U>
using alias_template = base<U>;
template <class U>
static constexpr int variable_template = 0;
};
template <class T>
struct derived: base<T> {
using typename base<T>::type; // Using base typedef
using base<T>::value; // Using base static data member
using base<T>::function; // Using base function members (regardless of template or not)
//using typename base<T>::alias_template; // DOES NOT SEEM TO WORK
//using base<T>::variable_template; // DOES NOT SEEM TO WORK
using typedef_test = type; // Working
static constexpr int value_test = value; // Working
using alias_template_test = alias_template<T>; // ERROR
static constexpr int variable_template_test = variable_template<T>; // ERROR
};
QUESTION: Is there a using
syntax to expose alias templates and variables templates inherited from a base class in order to make the currently erroneous lines compile? Is there any workaround to avoid to specify base<T>::
every single time in the derived class (here it remains simple, but in my actual code, specifying everytime rapidly becomes annoying)?
using
doesn't work this way for dependent member templates:
A using-declaration also can't be used to introduce the name of a dependent member template as a template-name (the template disambiguator for dependent names is not permitted)
I'm not sure if this will satisfy your requirements, but in order to make the alias work like a template, you could declare new member templates in the derived class defined in terms of the base's member templates:
template<typename U>
using alias_template = typename base<T>::template alias_template<U>;
template<typename U>
static constexpr auto variable_template = base<T>::template variable_template<U>;
However, IMO specifying base<T>::
every time is not a problem, and is cleaner than introducing new templates. You could even make it shorter with something like using Base = my_long_base_class_name<T>;