std::variant が特定の型を保持できるかどうかを確認するにはどうすればよいですか

編集: 私は実際にあなたの std::disjunction を掘り下げます アイデア、そしてそれは絶対に機能します。テンプレートの特殊化を使用して型リストを抽出するだけです。

私の古い学校の再帰的な混乱全体は単純になります:

template<typename T, typename VARIANT_T>
struct isVariantMember;

template<typename T, typename... ALL_T>
struct isVariantMember<T, std::variant<ALL_T...>> 
  : public std::disjunction<std::is_same<T, ALL_T>...> {};

元の回答: これを実現する簡単なテンプレートを次に示します。 false を返すことで機能します 空の型リストの場合。空でないリストの場合、true を返します。 最初の型が std::is_same<> を渡す場合

#include <vector>
#include <tuple>
#include <variant>

// Main lookup logic of looking up a type in a list.
template<typename T, typename... ALL_T>
struct isOneOf : public std::false_type {};

template<typename T, typename FRONT_T, typename... REST_T>
struct isOneOf<T, FRONT_T, REST_T...> : public 
  std::conditional<
    std::is_same<T, FRONT_T>::value,
    std::true_type,
    isOneOf<T, REST_T...>
  >::type {};

// Convenience wrapper for std::variant<>.
template<typename T, typename VARIANT_T>
struct isVariantMember;

template<typename T, typename... ALL_T>
struct isVariantMember<T, std::variant<ALL_T...>> : public isOneOf<T, ALL_T...> {};

// Example:
int main() {
  using var_t = std::variant<int, float>;

  bool x = isVariantMember<int, var_t>::value; // x == true
  bool y = isVariantMember<double, var_t>::value; // y == false

  return 0;
}

N.B.これを呼び出す前に、必ず T から cv および参照修飾子を削除してください (またはテンプレート自体に削除を追加してください)。それはあなたのニーズ次第です。


template <class T> struct type {};
template <class T> constexpr type<T> type_v{};

template <class T, class...Ts, template<class...> class Tp>
constexpr bool is_one_of(type<Tp<Ts...>>, type<T>) {
    return (std::is_same_v<Ts, T> || ...); 
}

次に is_one_of(type_v<VariantType>, type_v<T>) を使用します enable_if で .


既に C++17 を使用しているため、fold-expression を使用するとこれが簡単になります:

template <class T, class U> struct is_one_of;

template <class T, class... Ts> 
struct is_one_of<T, std::variant<Ts...>>
: std::bool_constant<(std::is_same_v<T, Ts> || ...)>
{ };

読みやすくするために、クラスにエイリアスを追加できます:

class GLCapabilities
{
public:
    using VariantType = std::variant<GLint64>;  // in future this would have other types
    template <class T> using allowed = is_one_of<T, VariantType>;

    template <typename T>
    std::enable_if_t<allowed<T>{}> AddCapability(const GLenum parameterName)
    { ... }
};