条件类型在 C++ 中定义?

conditional type define in c++?

我需要定义一个模板class A,根据模板参数中的嵌套类型,它有一个嵌套类型。像这样:

template<typename Container>
class A
{
public:
    using NestedType = if (Container has nested type Container::NestedTypeA)
    {
        Container::NestedTypeA;
    }
    else if (Container has nested type Container::NestedTypeB)
    {
        Container::NestedTypeB;
    }
    else
    {
        Container::NestedTypeC;
    }
};

如何实现这个using声明?或者有其他方法可以达到同样的效果吗?


感谢康桐薇和 Jarod42 的解答。但是这两个答案都使用了 C++20 的概念。最多用C++17怎么样?

在 C++20 中,您可以只使用概念

template<typename Container>
struct B { };

template<typename Container>
  requires requires { typename Container::NestedTypeA; } 
struct B<Container> {
  using NestedType = typename Container::NestedTypeA;
};

template<typename Container>
  requires requires { typename Container::NestedTypeB; } &&
         (!requires { typename Container::NestedTypeA; })
struct B<Container> {
  using NestedType = typename Container::NestedTypeB;
};

template<typename Container>
  requires requires { typename Container::NestedTypeC; } &&
         (!requires { typename Container::NestedTypeA; }) &&
         (!requires { typename Container::NestedTypeB; })
struct B<Container> {
  using NestedType = typename Container::NestedTypeC;
};

template<typename Container>
class A : public B<Container> {};

Demo

在C++17中,可以使用std::void_t检测成员类型的合法性。

#include <type_traits>

template<typename Container, typename = void>
constexpr bool HasNestedTypeA = false;
template<typename Container>
constexpr bool HasNestedTypeA<
  Container, std::void_t<typename Container::NestedTypeA>> = true;

template<typename Container, typename = void>
constexpr bool HasNestedTypeB = false;
template<typename Container>
constexpr bool HasNestedTypeB<
  Container, std::void_t<typename Container::NestedTypeB>> = true;

template<typename Container, typename = void>
constexpr bool HasNestedTypeC = false;
template<typename Container>
constexpr bool HasNestedTypeC<
  Container, std::void_t<typename Container::NestedTypeC>> = true;

template<
  typename Container, 
  bool = HasNestedTypeA<Container>,
  bool = HasNestedTypeB<Container>,
  bool = HasNestedTypeC<Container>>
struct B { };

template<typename Container>
struct B<Container, false, false, false> {};

template<typename Container, bool B1, bool B2>
struct B<Container, true, B1, B2> {
  using NestedType = typename Container::NestedTypeA;
};

template<typename Container, bool B1>
struct B<Container, false, true, B1> {
  using NestedType = typename Container::NestedTypeB;
};

template<typename Container>
struct B<Container, false, false, true> {
  using NestedType = typename Container::NestedTypeC;
};

template<typename Container>
class A : public B<Container> {};

Demo

有了 std::conditional_t 和适当的特征,你可以做这样的事情:

template <typename Container>
struct NestedTypeA
{
    using type = typename Container::NestedTypeA;
};

template <typename Container>
struct NestedTypeB
{
    using type = typename Container::NestedTypeB;
};

template <typename Container>
struct NestedTypeC
{
    using type = typename Container::NestedTypeC;
};

template <typename T>
constexpr bool hasNestedTypeA = requires{ typename T::NestedTypeA; };

template <typename T>
constexpr bool hasNestedTypeB = requires{ typename T::NestedTypeB; };

template<typename Container>
class A
{
public:
    using NestedType = typename std::conditional_t<
                            hasNestedTypeA<Container>,
                            NestedTypeA<Container>,
                            std::conditional_t<hasNestedTypeB<Container>,
                                               NestedTypeB<Container>,
                                               NestedTypeC<Container>>
                        >::type;
};

Demo