gpt4 book ai didi

C++ 如何基于部分特化创建 std::tuple 类型?

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:42:42 25 4
gpt4 key购买 nike

我有一个带有整数参数的模板,但基本模板被 static_assert() 禁用了像这样。 (我只想要一些特定的特殊化形式;我希望禁止传递给模板的任何参数,除了某些参数)

template<ItemID item_id> struct ItemTemplate{
static_assert(item_id == -1,"Cann't use unspecialized ItemTemplate!");
static ItemID id{ std::numeric_limits<ItemID>::max() };
//...
};

我也有这个模板的几个特化表格(我经常添加或删除其中的一些)

template<> struct ItemTemplate<1>{
static constexpr ItemID id{1};
//..
};
template<> struct ItemTemplate<2>{
static constexpr ItemID id{2};
//...
};

现在我想创建一个 std::tuple它仅由所有可用类型初始化。所以在上面的例子中,ItemTemplate<1>ItemTemplate<2> , 但不是 ItemTemplate<3>和其他非专业类型。我如何实现这一目标?

最佳答案

我看到了一个方法,但前提是你忘记了 static_assert()拒绝方式并定义 ItemTemplate 的特化.

下面是一个简化的例子,我只定义了 foo 的一些特化。和 foo通用结构保持未定义。

template <std::size_t>
struct foo;

template <> struct foo<2U> {};
template <> struct foo<3U> {};
template <> struct foo<5U> {};
template <> struct foo<7U> {};

现在您需要一些东西来检测类型是否已定义;例如,以下

template <typename T, std::size_t = sizeof(T)>
std::true_type existH (int);

template <typename>
std::false_type existH (long);

template <typename T>
using exist = decltype(existH<T>(0));

即:来自exist<foo<0>>::value你得到 false来自 exist<foo<2>>::value你得到 true .

现在您需要 foo 的索引列表(可用编译时间)从下限(例如,零)到上限定义的特化。

你可以用

template <std::size_t I, std::size_t topI, typename,
bool = (I == topI) || exist<foo<I>>::value>
struct fooIndexList;

template <std::size_t topI, std::size_t ... Ixs>
struct fooIndexList<topI, topI, std::index_sequence<Ixs...>, true>
{ using type = std::index_sequence<Ixs...>; };

template <std::size_t I, std::size_t topI, std::size_t ... Ixs>
struct fooIndexList<I, topI, std::index_sequence<Ixs...>, true>
{ using type = typename fooIndexList<I+1U, topI,
std::index_sequence<Ixs..., I>>::type; };

template <std::size_t I, std::size_t topI, std::size_t ... Ixs>
struct fooIndexList<I, topI, std::index_sequence<Ixs...>, false>
{ using type = typename fooIndexList<I+1U, topI,
std::index_sequence<Ixs...>>::type; };

使用 fooIndexList , 获得 std::tuple所有foo定义(从零到上限)非常简单:

template <std::size_t ... Idx>
constexpr auto makeFooTupleH (std::index_sequence<Idx...> const &)
{ return std::make_tuple( foo<Idx>{} ... ); }

constexpr auto makeFooTuple ()
{ return makeFooTupleH(
typename fooIndexList<0U, 100U, std::index_sequence<>>::type {}); }

在这个例子中上限是100但可以是 makeFooTuple() 的模板参数.

下面是一个完整的编译示例

#include <tuple>
#include <utility>
#include <iostream>
#include <type_traits>

template <typename T, std::size_t = sizeof(T)>
std::true_type existH (int);

template <typename>
std::false_type existH (long);

template <typename T>
using exist = decltype(existH<T>(0));

template <std::size_t>
struct foo;

template <> struct foo<2U> {};
template <> struct foo<3U> {};
template <> struct foo<5U> {};
template <> struct foo<7U> {};

template <std::size_t I, std::size_t topI, typename,
bool = (I == topI) || exist<foo<I>>::value>
struct fooIndexList;

template <std::size_t topI, std::size_t ... Ixs>
struct fooIndexList<topI, topI, std::index_sequence<Ixs...>, true>
{ using type = std::index_sequence<Ixs...>; };

template <std::size_t I, std::size_t topI, std::size_t ... Ixs>
struct fooIndexList<I, topI, std::index_sequence<Ixs...>, true>
{ using type = typename fooIndexList<I+1U, topI,
std::index_sequence<Ixs..., I>>::type; };

template <std::size_t I, std::size_t topI, std::size_t ... Ixs>
struct fooIndexList<I, topI, std::index_sequence<Ixs...>, false>
{ using type = typename fooIndexList<I+1U, topI,
std::index_sequence<Ixs...>>::type; };


template <std::size_t ... Idx>
constexpr auto makeFooTupleH (std::index_sequence<Idx...> const &)
{ return std::make_tuple( foo<Idx>{} ... ); }

constexpr auto makeFooTuple ()
{ return makeFooTupleH(
typename fooIndexList<0U, 100U, std::index_sequence<>>::type {}); }


int main ()
{
auto ft = makeFooTuple();

static_assert( std::is_same<decltype(ft),
std::tuple<foo<2U>, foo<3U>, foo<5U>, foo<7U>>>{}, "!");
}

限制:

  • 此解决方案仅在通用 foo 时有效未定义
  • 代码是C++14;如果你在 C++11 中需要它,它会稍微复杂一些
  • makeFooTuple() 的上限不能是一个很大的数字,因为 fooIndexList是递归的,因此受限于编译器的递归限制;您可以绕过此限制,但需要模式代码。

关于C++ 如何基于部分特化创建 std::tuple 类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46147579/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com