0

I am trying to explicitly instantiate a class with multiple different parameters.

// This is the class I want to explicitly instantiate
template <typename arg1, typename arg2>
class Foo{};

// This a helper meta-function to compute the template parameters for the above class
template <typename helper1, typename helper2>
class instantiation_helper{
    using arg1 = helper1; // actually some_constexpr_function(helper1, helper2)
    using arg2 = helper2; // actually some_constexpr_function(helper1 , helper2)
};

One trivial solution is verbose:

using helper0 = instantiation_helper<int, int>;
template class Foo<helper0::arg1, helper0::arg2>;

using helper1 = instantiation_helper<float, int>;
template class Foo<helper1::arg1, helper1::arg2>;

using helper2 = instantiation_helper<int, float>;
template class Foo<helper2::arg1, helper2::arg2>;

using helper3 = instantiation_helper<float, float>;
template class Foo<helper3::arg1, helper3::arg2>;

So I am storing the type of the Foo class in the helper meta-function itself and then instantiating using that:

template <typename helper1, typename helper2>
class instantiation_helper{
    using arg1 = helper1; // actually some_constexpr_function(helper1, helper2)
    using arg2 = helper2; // actually some_constexpr_function(helper1, helper2)
    using Foo_type = Foo<arg1, arg2>;
};

template instantiation_helper<int, int>::Foo_type;
template instantiation_helper<int, float>::Foo_type;
template instantiation_helper<float, int>::Foo_type;
template instantiation_helper<float, float>::Foo_type;

But this errors out with:

prog.cpp:13:50: error: expected unqualified-id before ‘;’ token
 template instantiation_helper<int, int>::Foo_type;

I guess this is because Foo_type does not qualify as simple-template-id (using typedef in template instantiation and extern template declaration).

So I am trying to instead store the template arguments as a tuple and then expand them later when explicitly instantiating:

template <typename helper1, typename helper2>
class instantiation_helper{
    using arg1 = helper1; // actually some_constexpr_function(helper1, helper2)
    using arg2 = helper2; // actually some_constexpr_function(helper1, helper2)
    using Foo_template_params = std::tuple<arg1, arg2>;
};

using arg_list1 = instantiation_helper<int, int>::Foo_template_params;
template class Foo<std::tuple_element<0, arg_list1>::type, std::tuple_element<1, arg_list1>::type>;

using arg_list2 = instantiation_helper<float, int>::Foo_template_params;
template class Foo<std::tuple_element<0, arg_list2>::type, std::tuple_element<1, arg_list2>::type>;

using arg_list3 = instantiation_helper<int, float>::Foo_template_params;
template class Foo<std::tuple_element<0, arg_list3>::type, std::tuple_element<1, arg_list3>::type>;

using arg_list4 = instantiation_helper<float, float>::Foo_template_params;
template class Foo<std::tuple_element<0, arg_list4>::type, std::tuple_element<1, arg_list4>::type>;

This obviously again is verbose and I am not even sure if tuple is the right way of doing this.

So my question is:

  1. How would one go about achieving this?
  2. What if Foo had a third variadic template parameter like
template <typename arg1, typename arg2, typename ...arg3>
class Foo{};
  • In the first error you lack `class` keyword (`template instantiation_helper`); my experience is that e.g. `template class instantiation_helper::Foo_type::Foo` should work in GCC, but won't work in Clang. – Tomáš Kolárik Feb 10 '21 at 17:37
  • Also, it is worth mentioning that the solution I suggested should be standard-compliant, see https://stackoverflow.com/questions/11414817/code-duplication-between-typedefs-and-explicit-instantiations , I will try to send a ticket on Clang bugtracker. – Tomáš Kolárik Feb 10 '21 at 17:59
  • Ticket on Clang with more details: https://bugs.llvm.org/show_bug.cgi?id=49133 – Tomáš Kolárik Feb 19 '21 at 13:24

0 Answers0