【问题标题】:Is it possible to check if a type has been instantiated with a specific template parameter?是否可以检查类型是否已使用特定模板参数实例化?
【发布时间】:2021-01-25 19:14:38
【问题描述】:

不太确定我的术语是否 100% 正确,所以这里是代码:

template<class... Ts>
struct Empty { };

int main() {
   using T = Empty<int, double>;
   // How to check if T "contains" double?

   return 0;
}

所以这专门用于接受多种模板类型的类型。理想情况下,这也是在编译时。如果不需要该类型的对象,则加分。

我能得到的最接近(help)是这样的:

template <class check, class T, class... U>
constexpr bool contains_type(){
   if constexpr (std::is_same_v<T, check>)
      return true;
   else if constexpr (sizeof...(U) > 0)
      return contains_type<check, U...>();
   else
      return false;
}


template <class check, template<class> class TypeToCheck, class... T>
constexpr bool does_obj_contain_type(TypeToCheck<T...>) {
   if constexpr (sizeof...(T) > 0)
      return contains_type<check, T...>();
   else
      return false;
}

constexpr bool does_contain_double = does_obj_contain_type<double>(T{});

它包含我从未见过的 C++ 语法,但它确实有效。如果它不需要T{} 对象,那就太好了。也许看起来更清醒一些。

【问题讨论】:

  • 您可以将T{}替换为std::declval&lt;T&gt;()
  • 哦,对了,我读到了它,并认为有一天我会使用它。今天有一些,谢谢。

标签: c++ templates c++17 variadic-templates template-meta-programming


【解决方案1】:

不确定你到底想要什么……但我想是这样的

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{});

但如果你不能实例化T 类型的对象,那就是个问题了。在这种情况下,我想您可以使用类/结构特化。

某事

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>();

或者作为模板变量可能更好value(super 建议:谢谢!)

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>;

【讨论】:

  • @eerorika - 如果我没记错的话,用||折叠是false,以防空列表。
  • 这样就简单多了,谢谢。可惜没有参数似乎是不可能的。但是std::declval 应该不会太丑。
  • @Basti - 添加了一个替代版本,以防您不想实例化 T 类型的对象(注意:代码未经测试)。
  • 我明白了。在实践中不是问题,我主要是好奇它是否可能。再次感谢。
  • @Basti - 如果您不需要T 类型的对象,最好检查类型本身而不是对象(恕我直言)。不幸的是,需要更多的打字。
【解决方案2】:

这个问题已经得到解答,但如果你想在某个时候解开 Empty&lt;&gt;s 的层,我会添加一个扩展。

#include <iostream>
#include <type_traits>

// non templated types
template<class check, class... Ts>
struct contains_type {
    static constexpr bool value = (std::is_same_v<check, Ts> || ...);
};

// templated types
template <class check, template<class...> class TypeToCheck, class... Ts>
struct contains_type<check, TypeToCheck<Ts...>> {
    static constexpr bool value = 
        (std::is_same_v<check, Ts> || ...) ||     // if "check" is templated
        (contains_type<check, Ts>::value || ...); // unwrap one layer
};

// Helper variable template
template<class... Ts>
inline constexpr bool contains_type_v = contains_type<Ts...>::value;

template<class... Ts>
struct Empty { };

int main() {
   using False = Empty<int, float, float, long double>;
   using True = Empty<int, double, int>;
   using DoubleNestFalse = Empty<Empty<int>, Empty<int, float>>;
   using DoubleNestTrue = Empty<Empty<int>, Empty<double, float>>;
   
   std::cout << std::boolalpha;

   std::cout << contains_type_v<double, False> << '\n';
   std::cout << contains_type_v<double, True> << '\n';
   
   std::cout << contains_type_v<double, float> << '\n';              // false
   std::cout << contains_type_v<double, int, double> << '\n';        // true
 
   std::cout << contains_type_v<double, DoubleNestFalse> << '\n';
   std::cout << contains_type_v<double, DoubleNestTrue> << '\n';

   std::cout << contains_type_v<Empty<int>, DoubleNestTrue> << '\n'; // true
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-10-21
    • 1970-01-01
    • 2021-12-26
    • 1970-01-01
    • 1970-01-01
    • 2013-10-02
    • 2012-06-30
    • 1970-01-01
    相关资源
    最近更新 更多