我有一个函数,它采用模板类型来确定返回值。是否有任何方法在编译时判断模板类型是否是模板类的实例化?
例如。
class First { /* ... */ };
template <typename T>
class Second { /* ... */ };
using MyType = boost::variant<First, Second<int>, Second<float>>;
template <typename SecondType>
auto func() -> MyType {
static_assert(/* what goes here?? */, "func() expects Second type");
SecondType obj;
// ...
return obj;
}
MyType obj = func<Second<int>>();我知道有可能通过做
template <typename T>
auto func() -> MyType {
static_assert(std::is_same<T, int>::value || std::is_same<T, float>::value,
"func template must be type int or float");
Second<T> obj;
// ...
return obj;
}
MyType obj = func<int>();一般来说,我只是好奇是否有一种方法来测试某个类型是否是模板类的实例化?因为如果MyType最终有6个Second实例化,我不想测试所有可能的类型。
发布于 2017-05-16 23:09:15
这里有一个选择:
#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
}它基本上是对模板实例化类型的is_instance结构进行专门化。
发布于 2017-05-16 23:56:06
另一种选择是,听听亨利的评论:
#include <iostream>
#include <type_traits>
#include <string>
template <class, template <class, class...> class>
struct is_instance : public std::false_type {};
template <class...Ts, template <class, class...> class U>
struct is_instance<U<Ts...>, U> : public std::true_type {};
template <class>
class Second
{};
template <class, class, class>
class Third
{};
int main()
{
using A = Second<int>;
using B = Second<std::string>;
using C = float;
using D = Third<std::string, int, void>;
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
std::cout << is_instance<D, Third>{} << '\n'; // prints 1
}发布于 2020-04-05 10:11:11
对@RichardHodges的回答的另一个改进是:通常,人们不仅希望捕获普通类型,而且希望捕获所有cv限定类型和ref限定类型。
换句话说,如果is_instance<A, Second>{}是真的,那么is_instance<A const&, Second>{}或is_instance<A&&, Second>{}也应该是真。这个线程中的当前实现不支持这一点。
以下代码说明了所有cv-ref限定类型,方法是添加另一个间接方向和一个std::decay_t。
namespace
{
template <typename, template <typename...> typename>
struct is_instance_impl : public std::false_type {};
template <template <typename...> typename U, typename...Ts>
struct is_instance_impl<U<Ts...>, U> : public std::true_type {};
}
template <typename T, template <typename ...> typename U>
using is_instance = is_instance_impl<std::decay_t<T>, U>;把它当作
#include <iostream>
template <typename ...> struct foo{};
template <typename ...> struct bar{};
int main()
{
std::cout << is_instance<foo<int>, foo>{} << std::endl; // prints 1
std::cout << is_instance<foo<float> const&, foo>{} <<std::endl; // prints 1
std::cout << is_instance<foo<double,int> &&, foo>{} << std::endl; // prints 1
std::cout << is_instance<bar<int> &&, foo>{} << std::endl; // prints 0
}https://stackoverflow.com/questions/44012938
复制相似问题