How can I check if a type is an instantiation of a given class template?
I came up with the following solution, using C++11 variadic templates and simple partial specialization:
#include <type_traits>
template < template <typename...> class Template, typename T >
struct is_instantiation_of : std::false_type {};
template < template <typename...> class Template, typename... Args >
struct is_instantiation_of< Template, Template<Args...> > : std::true_type {};
It could be adapted to C++03 by using the preprocessor to generate versions for a varying number of template parameters, but there is maybe a simpler way.
C++11: How to check if a type is an instantiation of a given class-template of heterogeneous NON-TYPE parameters?
You have probably hit a compiler bug. I tried to reduce this to a simpler example:
#include <iostream>
template<bool, char> struct A { };
template<typename... Ts>
struct test
{
template<typename T>
struct impl : std::false_type {};
template<Ts... Args>
struct impl<A<Args...>> : std::true_type {};
};
int main()
{
using IA = A<false, 'x'>;
std::cout << ((test<bool, char>::impl<IA>::value) ? "Y" : "N");
}
GCC 4.7.2 compiles this, but the compiled program prints the wrong output (N
). On the other hand, Clang 3.2 gets this right, and the compiled program prints the correct output (Y
).
Here is a slightly modified version of the above program, where the test
class template much resembling your is_instantiation_of__nontypes_v2__
class template:
#include <iostream>
template<bool, char> struct A {};
template<typename... Ts>
struct test
{
template<template<Ts...> class TT, typename T>
struct impl : std::false_type {};
template<template<Ts...> class TT, Ts... Args>
struct impl<TT, TT<Args...>> : std::true_type {};
};
int main()
{
using IA = A<false, 'x'>;
std::cout << ((test<bool, char>::impl<A, IA>::value) ? "Y" : "N");
}
While Clang compiles this and the compiled program prints the correct output (Y
), GCC emits the following compilation error:
expected a template of type
'template<class ... Ts> template<Ts ...<anonymous> > class TT'
, got'template<bool <anonymous>, char <anonymous> > struct A'
.
It looks like GCC does not recognize that the first template template parameter should have a template argument list given by the expansion of Ts
. Therefore, it seems to me this is a bug of GCC.
How to tell if template type is an instance of a template class?
Here's an option:
#include <iostream>
#include <type_traits>
#include <string>
template <class, template <class> class>
struct is_instance : public std::false_type {};
template <class T, template <class> class U>
struct is_instance<U<T>, U> : public std::true_type {};
template <class>
class Second
{};
int main()
{
using A = Second<int>;
using B = Second<std::string>;
using C = float;
std::cout << is_instance<A, Second>{} << '\n'; // prints 1
std::cout << is_instance<B, Second>{} << '\n'; // prints 1
std::cout << is_instance<C, Second>{} << '\n'; // prints 0
}
It's basically specializing the is_instance
struct for types that are instantiations of a template.
Is it possible to check if a type has been instantiated with a specific template parameter?
Not sure to understand what do you exactly want... but I suppose is something as
template <class check, template<class...> class TypeToCheck, class... T>
constexpr bool does_obj_contain_type(TypeToCheck<T...>) {
return (std::is_same_v<check, T> || ...);
}
// ...
using T = Empty<int, double>;
auto x = does_obj_contain_type<double>(T{});
But it's a problem if you can't instantiate an object of type T
. In the case, I suppose you can use class/struct specialization.
Something as
template <typename>
struct does_obj_contain_type;
template <template <typename...> class TTC, typename ... Ts>
struct does_obj_contain_type<TTC<Ts...>>
{
template <typename check>
static constexpr bool func ()
{ return (std::is_same_v<check, Ts> || ...); }
};
// ...
using T = Empty<int, double>;
constexpr auto x = does_obj_contain_type<T>::func<double>();
Or maybe better as a template variable value
(suggested by super: thanks!)
template <template <typename...> class TTC, typename ... Ts>
struct does_obj_contain_type<TTC<Ts...>>
{
template <typename Check>
static constexpr auto value = (std::is_same_v<Check, Ts> || ...);
};
// ...
using T = Empty<int, double>;
constexpr auto x = does_obj_contain_type<T>::value<double>;
How to check if a type is instantiated from a certain variadic template class in a template function?
You can create a trait to test for instantiations of Foo
, and then fold it across all your parameters.
template <typename>
struct is_foo : std::false_type {};
template <typename... Ts>
struct is_foo<Foo<Ts...>> : std::true_type {};
template <typename T>
constexpr bool is_foo_v = is_foo<T>::value;
template <typename... T>
void Bar(const T&... arguments) {
static_assert((is_foo_v<T> && ...), "arguments must all be Foos");
}
See it on coliru
Detect the existence of a template instantiation for a given type
Here's a link-time solution. Works on GCC, Clang, and MSVC.
One template (impl::Checker<T>
) declares a friend function and calls it.
Another template (impl::Marker
) defines that function. If it's not defined, the first class gets an undefined reference.
run on gcc.godbolt.org
#include <cstddef>
#include <type_traits>
namespace impl
{
template <typename T>
struct Checker
{
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wnon-template-friend"
#endif
friend void adl_MarkerFunc(Checker<T>);
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic pop
#endif
static std::nullptr_t Check()
{
adl_MarkerFunc(Checker<T>{});
return nullptr;
}
inline static const std::nullptr_t check_var = Check();
static constexpr std::integral_constant<decltype(&check_var), &check_var> use_check_var{};
};
template <typename T>
struct Marker
{
friend void adl_MarkerFunc(Checker<T>) {}
};
}
template <typename T, impl::Checker<T> = impl::Checker<T>{}>
struct Access
{
template <typename U>
void Read()
{
static_assert(std::is_same_v<T, U>);
(void)impl::Marker<U>{};
}
};
int main()
{
Access<int> x;
x.Read<int>();
[[maybe_unused]] Access<float> y; // undefined reference to `impl::adl_MarkerFunc(impl::Checker<float>)'
using T [[maybe_unused]] = Access<double>; // undefined reference to `impl::adl_MarkerFunc(impl::Checker<double>)'
}
Had to introduce a dummy template parameter to Access
, since I couldn't think of any other way of detecting it being used in a using
.
How to check if an object is an instance of a template class in C++?
This is pretty straightforward using a specialized helper class:
#include <type_traits>
#include <iostream>
template<typename T> class A {};
template<typename T>
struct is_a : std::false_type {};
template<typename T>
struct is_a<A<T>> : std::true_type {};
int main()
{
auto a1=A<int>{};
bool b1=false;
std::cout << is_a<decltype(a1)>::value << std::endl;
std::cout << is_a<decltype(b1)>::value << std::endl;
return 0;
}
is_a
gets specialized for a template parameter that's any instance of A
. The non-specialized version is the false trait, and the specialized version is the true trait, and that's pretty much it. If you are not familiar with the topic of template specialization, this is a fairly involved and deep topic that should have a full explanation in every good C++ textbook, and I refer you there for a full and complete discussion on this topic.
C++ Concepts: checking for template instantiation
Using C++17 class template argument deduction, you should be able to do something like this:
template<typename A, typename B, typename C>
struct mytype { };
template<class T>
concept C1 = requires(T x) {
{ mytype{x} } -> std::same_as<T>;
};
mytype{x}
uses class template argument deduction to deduce A
, B
and C
, so this is valid if you can construct a mytype<A, B, C>
from a T
. In particular, this is valid if mytype
is copy-constructible since you have an implicitly declared copy-deduction guide similar to:
template <typename A, typename B, typename C>
mytype(mytype<A, B, C>) -> mytype<A, B, C>;
Checking that T
is also the constructed mytype
instantiation avoid matching other deduction guides, e.g., this would match for any type without the -> std::same_as<T>
:
template <class A, class B, class C>
struct mytype {
mytype(A);
};
template <class A>
mytype(A) -> mytype<A, A, A>;
The proposed solution does not work for non copy-constructible classes, even though should be possible to make it work for move-only classes.
Tested with clang and gcc: https://godbolt.org/z/ojdcrYqKv
How to check if an object is an instance of template class of multiple template arguments and that one of said arguments fulfills some condition?
You were on the right track:
#include <type_traits>
#include <iostream>
template <typename T1, typename T2>
struct A
{
};
template <typename Type, typename=void>
struct IsA: std::false_type
{
};
template <typename T1, typename T2>
struct IsA<A<T1, T2>, std::enable_if_t<std::is_same_v<T2, int>>>
: std::true_type
{
};
int main()
{
std::cout << IsA<int>::value << "\n";
std::cout << IsA<A<char, char>>::value << "\n";
std::cout << IsA<A<char, int>>::value << "\n";
return 0;
}
In this trivial example the "some condition" is just a std::is_same_v<T2, int>
, only for the sake of an example.
Related Topics
What Is Better, Adjacency Lists or Adjacency Matrices for Graph Problems in C++
Should I Store Entire Objects, or Pointers to Objects in Containers
Reorder Vector Using a Vector of Indices
Why Is My Log in the Std Namespace
Understanding Recursion to Generate Permutations
How to Properly Use Std::String on Utf-8 in C++
C++ HTML Template Framework, Templatizing Library, HTML Generator Library
How to Hook Windows Functions in C/C++
Explain C++ Sfinae to a Non-C++ Programmer
I'Ve Heard I++ Isn't Thread Safe, Is ++I Thread-Safe
C++11 Lambda Implementation and Memory Model
C++ Issue with Function Overloading in an Inherited Class
Are Static Variables in a Base Class Shared by All Derived Classes