Having seen this answer, I tried to come up with a variable template utility to the code from it:
template <class T, template <class...> class Template>
struct is_specialization : std::false_type {};
template <template <class...> class Template, class... Args>
struct is_specialization<Template<Args...>, Template> : std::true_type {};
And implement it like so:
template <template <class...> class Template, class... Args>
constexpr bool is_specialization_v = is_specialization<Template<Args...>, Template>::value;
because that's how I saw similar utilities to be implemented in the header file of <type_traits>
. E.g.:
template <typename _Tp, typename _Up>
inline constexpr bool is_same_v = is_same<_Tp, _Up>::value;
template <typename _Base, typename _Derived>
inline constexpr bool is_base_of_v = is_base_of<_Base, _Derived>::value;
template <typename _From, typename _To>
inline constexpr bool is_convertible_v = is_convertible<_From, _To>::value;
etc. (GCC 8.2.0 implementation from MinGW)
But the problem is that, while the ::value
syntax seems to work, the *_v
syntax does not:
int main() {
bool foo = is_specialization<std::vector<int>, std::vector>::value; // No problem
bool bar = is_specialization_v<std::vector<int>, std::vector>; // compilation error!
std::cout << foo << ' ' << bar;
}
This produces the following error:
error: type/value mismatch at argument 1 in template parameter list for 'template<template<class ...> class Template, class ... Args> constexpr const bool is_specialization_v<Template, Args ...>' bool bar = is_specialization_v<std::vector<int>, std::vector>; // compilation error! ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ note: expected a class template, got 'std::vector<int>' error: type/value mismatch at argument 2 in template parameter list for 'template<template<class ...> class Template, class ... Args> constexpr const bool is_specialization_v<Template, Args ...>' expected a type, got 'vector'
Why is that? To be honest, the error seems fair to me and got me thinking how exactly does the code in the aforementioned answer work. It expects a class
template and a parameter pack, but it's given a class
, then a pack. On the other hand, it's specialised on the combination of those two types and it confuses me slightly. I would like to know:
- What is the deduction process here? The linked answer does not go in detail on how the code works.
- How to introduce the
*_v
variable template utility in this case?