1

The boost::mpl::apply metafunction only works with template type arguments. For instance, the following works:

using namespace boost::mpl;

template <class U, class S = int>
struct Bar { };

using BarInt = apply<Bar<_1>, int>::type;

However, if I have a separate class template with a non-type argument:

template <class U, int S = 50>
struct Quux { };

using QuuxInt = apply<Quux<_1>, int>::type;

I get a compile error like:

/usr/include/boost/mpl/aux_/preprocessed/gcc/apply_wrap.hpp:36:8: error: no class template named ‘apply’ in ‘struct Quux<mpl_::arg<1> >’
 struct apply_wrap1
        ^
foo.cxx: In function ‘int main()’:
foo.cxx:25:21: error: expected type-specifier
     using QuuxInt = apply<Quux<_1>, int>::type;
                     ^

Is there a way around this, besides just creating a subtype for Bar that makes all the non-type arguments into type arguments?

Barry
  • 286,269
  • 29
  • 621
  • 977

1 Answers1

1

No, there's no way around it. You'll have to write a wrapper. Thankfully, if you make your wrapper a metafunction that takes type arguments that unwrap to the expected non-type arguments:

template <class U, class S = std::integral_constant<int, 50>>
struct QuuxWrap {
    using type = Quux<U, S::value>;
};

Then simply applying on QuuxWrap gets you what you want:

using QuuxInt = apply<QuuxWrap<_1>, int>::type;
// QuuxInt is Quux<int, 50>

Values are the red-headed stepchildren of template metaprogramming. If you lift all your values to types, everything becomes a lot easier to deal with.

Barry
  • 286,269
  • 29
  • 621
  • 977