条件类型在 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> {};
在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> {};
有了 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;
};
我需要定义一个模板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> {};
在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> {};
有了 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;
};