This code:
#include <memory>
template <template <typename> class Ptr>
class A { Ptr<int> ints; };
using B = A<std::unique_ptr>;
yields the following error (with GCC 6.3):
a.cpp:6:28: error: type/value mismatch at argument 1 in template parameter list for ‘template<template<class> class Ptr> class A’
using B = A<std::unique_ptr>;
^
a.cpp:6:28: note: expected a template of type ‘template<class> class Ptr’, got ‘template<class _Tp, class _Dp> class std::unique_ptr’
Now, I can work around this, like so:
template <typename T>
using plugged_unique_ptr = std::unique_ptr<T>;
using B = A<plugged_unique_ptr>;
but why do I have to? I mean, why isn't the compiler willing to "plug" the second template parameter of std::unique_ptr
with its default value and allow std::unique_ptr
to be used as a template argument to A
?
Because template template parameters need to match exactly. This means the default template argument is not relevant here. Note that extending your template template argument to two template arguments will only work by chance: an implementation is permitted to add more template arguments than defined by the standard, and some often do in the case of SFINAE around std containers.
This is also the prime reason I generally advise against using any template template arguments, and instead just use a plain template typename. If you need access to nested template types, provide internal accessors in line of e.g. value_type
or external accessors such as tuple_element
to access these inside the template.
Note: This apparently has changed in C++17, where the matching is not exact anymore, but slightly relaxed yet more complicated. Nevertheless, I would still advise against using template template parameters in general.
std::unique_ptr
has a second template argument with a default so template <typename> class Ptr
doesn't match std::unique_ptr
template <typename...> class Ptr
will work
cppreference
As @HolyBlackCat suggests, we no longer have to use any workaround with C++17 - and OP's code does indeed compile (coliru.com).
GCC 6.3.0 compiles C++14 code by default and doesn't apply this language semantics change.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With