Sana static_assert()
inkar yolunu unutup ItemTemplate
ait sadece uzmanlık tanımlamak yalnızca bir şekilde görmek ama. Aşağıdakiler, yalnızca foo
bazı uzmanlıklarını tanımladığım ve foo
genel yapısının tanımlanmamış kaldığı basitleştirilmiş bir örnektir.
template <std::size_t>
struct foo;
template <> struct foo<2U> {};
template <> struct foo<3U> {};
template <> struct foo<5U> {};
template <> struct foo<7U> {};
Artık bir tür tanımlanıp tanımlanmadığını tespit etmek için bir şeye ihtiyacınız var; exist<foo<0>>::value
sizi false
almak ve exist<foo<2>>::value
sizi true
olsun: Örneğin gereği,
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));
aşağıdaki.
Artık bir alt sınıra (örneğin sıfır) bir üst sınıra tanımlanan foo
uzmanlık indekslerinin bir listesini (kullanılabilir derleme süresi) kullanmanız gerekir.
için
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; };
(sıfırdan bir üst limit) gibi tanımlanmıştır foo
çok basit her bir std::tuple
elde edilmesi, fooIndexList
kullanılması ile elde edilebilir: Örnekte
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 {}); }
Üst sınır 100
'dir, ancak makeFooTuple()
şablon parametresi olabilir.
aşağıdaki
#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>>>{}, "!");
}
Sınırları tam derleme örnektir: jenerik foo
tanımlı değilse
- bu çözüm sadece çalışır
- kodudur C++ 14; C++ 11'de ihtiyacınız varsa,
makeFooTuple()
numaralı telefonun üst sınırı makeFooTuple()
üst sınırında çok daha karmaşık olamaz, çünkü fooIndexList
tekrarlayıcıdır, bu nedenle derleyicinin yineleme sınırı tarafından sınırlanır; Bu sınırı atlayabilir, ancak mod kodunu girebilirsiniz.
'ItemID' nedir?ItemTemplate <-1> 'gibi görünüyor, statik iddiayı tetiklemez. Bir [mcve] burada yararlı olur. –
Bu std :: uint32, ve ben bu nokta @Sam Varshavchik –
Hayır olduğunu sanmıyorum, tam olarak bu noktada. Bir 'ItemId ',' std :: tuple, ItemTemplate <5>> 'için bir imzasız hata, bir statik hataya çarptığından bir derleme hatası atar. Sorunuz açık değil. Sorunuz, tüm mevcut uzmanlıkların otomatik olarak nasıl numaralandırılacağıyla ilgili ise, bu C++'da mümkün değildir. Bunu kendiniz açıkça uygulamak zorunda kalacaksınız. –