如何在编译时从一些不同的类型中选择类型?
How to choose type from some different on compilation time?
我想做这样的事情:
template <uint64_t N>
struct a {
static constexpr T1 v1 = {};
static constexpr T2 v2 = {};
static constexpr auto v3 = (N % 2 == 1 ? v1 : v2);
};
但我不能对不同的类型使用 (? :)。我该怎么做?
例如,您可以使用 if constexpr
和一个 lambda 函数 (C++17):
template <std::uint64_t N>
struct a {
static constexpr T1 v1 = {};
static constexpr T2 v2 = {};
static constexpr auto v3 =
[] {
if constexpr (N % 2 == 1)
return v1;
else
return v2;
}();
};
另一个带有 std::tuple
(C++14) 的解决方案:
template <std::uint64_t N>
struct a {
static constexpr T1 v1 = {};
static constexpr T2 v2 = {};
static constexpr auto v3 = std::get<N % 2>(std::make_tuple(v2, v1));
};
如果您可以使用 C++17(但您仅标记了 C++11 和 C++14),则最好使用基于 if constexpr
的解决方案(非常优雅,基于 Evg 的 lambda),恕我直言。
在C++17之前,我想你可以尝试使用SFINAE。举个例子
#include <type_traits>
template <int N>
struct Foo
{
static constexpr int v1 = {};
static constexpr long v2 = {};
template <int M = N>
constexpr static std::enable_if_t<M % 2 == 1, int> getV3 ()
{ return v1; }
template <int M = N>
constexpr static std::enable_if_t<M % 2 != 1, long> getV3 ()
{ return v2; }
static constexpr auto v3 = getV3();
};
int main ()
{
static_assert( std::is_same_v<int const, decltype(Foo<1>::v3)> );
static_assert( std::is_same_v<long const, decltype(Foo<2>::v3)> );
}
根据 Evg 的建议(谢谢!),您可以避免使用重载(good-old 标签调度)SFINAE。举个例子
template <int N>
struct Foo
{
static constexpr int v1 = {};
static constexpr long v2 = {};
constexpr static auto getV3 (std::true_type)
{ return v1; }
constexpr static auto getV3 (std::false_type)
{ return v2; }
static constexpr auto v3 = getV3(std::integral_constant<bool, N%2>{});
};
我想做这样的事情:
template <uint64_t N>
struct a {
static constexpr T1 v1 = {};
static constexpr T2 v2 = {};
static constexpr auto v3 = (N % 2 == 1 ? v1 : v2);
};
但我不能对不同的类型使用 (? :)。我该怎么做?
例如,您可以使用 if constexpr
和一个 lambda 函数 (C++17):
template <std::uint64_t N>
struct a {
static constexpr T1 v1 = {};
static constexpr T2 v2 = {};
static constexpr auto v3 =
[] {
if constexpr (N % 2 == 1)
return v1;
else
return v2;
}();
};
另一个带有 std::tuple
(C++14) 的解决方案:
template <std::uint64_t N>
struct a {
static constexpr T1 v1 = {};
static constexpr T2 v2 = {};
static constexpr auto v3 = std::get<N % 2>(std::make_tuple(v2, v1));
};
如果您可以使用 C++17(但您仅标记了 C++11 和 C++14),则最好使用基于 if constexpr
的解决方案(非常优雅,基于 Evg 的 lambda),恕我直言。
在C++17之前,我想你可以尝试使用SFINAE。举个例子
#include <type_traits>
template <int N>
struct Foo
{
static constexpr int v1 = {};
static constexpr long v2 = {};
template <int M = N>
constexpr static std::enable_if_t<M % 2 == 1, int> getV3 ()
{ return v1; }
template <int M = N>
constexpr static std::enable_if_t<M % 2 != 1, long> getV3 ()
{ return v2; }
static constexpr auto v3 = getV3();
};
int main ()
{
static_assert( std::is_same_v<int const, decltype(Foo<1>::v3)> );
static_assert( std::is_same_v<long const, decltype(Foo<2>::v3)> );
}
根据 Evg 的建议(谢谢!),您可以避免使用重载(good-old 标签调度)SFINAE。举个例子
template <int N>
struct Foo
{
static constexpr int v1 = {};
static constexpr long v2 = {};
constexpr static auto getV3 (std::true_type)
{ return v1; }
constexpr static auto getV3 (std::false_type)
{ return v2; }
static constexpr auto v3 = getV3(std::integral_constant<bool, N%2>{});
};