我试图根据一些枚举值创建(在编译时)结构体结构。我会编写代码,它更容易解释:
enum class EnumTest {A,B,C,D,E,F};
template<class EnumType, EnumType enumValue>
struct MappedStruct
{
int element = 0;
};
template<class EnumType, EnumType enumValue>
struct VecStruct
{
std::vector<MappedStruct<EnumType, enumValue>> vec;
};
template<class EnumType, EnumType... enumValues>
class MapperSelection
{
public:
template<EnumType type>
void insert(int arg) {mapper_<EnumType, type>.vec.push_back(arg); // * compilation error here *
}
private:
VecStruct<EnumType, enumValues...> mapper_;
};
int main()
{
MapperSelection< EnumTest::A, EnumTest::B, EnumTest::C> selection;
selection.insert<EnumTest::>(100);
return 0;
}
有没有办法编译这段代码?或一些解决方法具有相同的行为?可能与所有的枚举?
答案 0 :(得分:1)
对我来说并不完全清楚,但我认为你想要的是这样的:
#include <vector>
#include <ostream>
#include <tuple>
#include <iostream>
struct A { static constexpr const char* name() { return "A"; }};
struct B { static constexpr const char* name() { return "B"; }};
struct C { static constexpr const char* name() { return "C"; }};
template<class Tag>
struct tagged_vector : std::vector<int>
{
using std::vector<int>::vector;
};
template<class...Tags>
struct selection
{
using storage_type = std::tuple<tagged_vector<Tags>...>;
template<class Tag>
void add(Tag, int value)
{
std::get<tagged_vector<Tag>>(storage_).push_back(value);
}
template<std::size_t I>
static const char* make_sep(std::integral_constant<std::size_t, I>) {
return "\n";
}
static const char* make_sep(std::integral_constant<std::size_t, 0>) {
return "";
};
template<class Tag>
static void impl_report(std::ostream& os, tagged_vector<Tag> const& vec, const char* sep)
{
os << sep << Tag::name() << " ";
std::copy(std::begin(vec), std::end(vec), std::ostream_iterator<int>(os, ", "));
}
template<class Tuple, std::size_t...Is>
static void impl_report(std::ostream& os, Tuple&& tup, std::index_sequence<Is...>)
{
using expand = int[];
void(expand{0,
(impl_report(os, std::get<Is>(tup), make_sep(std::integral_constant<std::size_t, Is>())), 0)...
});
};
std::ostream& report(std::ostream& os) const {
impl_report(os, storage_, std::make_index_sequence<std::tuple_size<storage_type>::value>());
return os;
}
storage_type storage_;
};
int main()
{
auto sel = selection<A, B, C>();
sel.add(A(), 100);
sel.add(A(), 101);
sel.add(B(), 90);
sel.add(C(), 10);
sel.add(C(), 11);
sel.report(std::cout) << std::endl;
}
预期产出:
A 100, 101,
B 90,
C 10, 11,
标签是类型还是枚举(可能)并不重要,但如果您可以使用它们,类型将使生活更轻松。
<强>更新强>
用枚举重新实现。请注意,它不够整洁,需要更多关于用户的知识。在c ++设计中,这通常被视为一件坏事:
#include <vector>
#include <ostream>
#include <tuple>
#include <iostream>
enum class my_tag
{
A,B,C
};
const char* name(my_tag t)
{
switch(t) {
case my_tag ::A:
return "A";
case my_tag ::B:
return "B";
case my_tag ::C:
return "C";
}
return "logic error";
}
template<class TagType, TagType TagValue>
struct tagged_vector : std::vector<int>
{
using std::vector<int>::vector;
};
template<class TagType, TagType...Tags>
struct selection
{
using storage_type = std::tuple<tagged_vector<TagType, Tags>...>;
template<TagType Tag>
void add(int value)
{
std::get<tagged_vector<TagType, Tag>>(storage_).push_back(value);
}
template<std::size_t I>
static const char* make_sep(std::integral_constant<std::size_t, I>) {
return "\n";
}
static const char* make_sep(std::integral_constant<std::size_t, 0>) {
return "";
};
template<TagType Tag>
static void impl_report(std::ostream& os, tagged_vector<TagType, Tag> const& vec, const char* sep)
{
os << sep << name(Tag) << " ";
std::copy(std::begin(vec), std::end(vec), std::ostream_iterator<int>(os, ", "));
}
template<class Tuple, std::size_t...Is>
static void impl_report(std::ostream& os, Tuple&& tup, std::index_sequence<Is...>)
{
using expand = int[];
void(expand{0,
(impl_report(os, std::get<Is>(tup), make_sep(std::integral_constant<std::size_t, Is>())), 0)...
});
};
std::ostream& report(std::ostream& os) const {
impl_report(os, storage_, std::make_index_sequence<std::tuple_size<storage_type>::value>());
return os;
}
storage_type storage_;
};
int main()
{
auto sel = selection<my_tag, my_tag::A, my_tag::B, my_tag::C>();
sel.add<my_tag::A>(100);
sel.add<my_tag::A>(101);
sel.add<my_tag::B>(90);
sel.add<my_tag ::C>(10);
sel.add<my_tag ::C>(11);
sel.report(std::cout) << std::endl;
}
更新了c ++ 11 ghastliness :
#include <vector>
#include <ostream>
#include <tuple>
#include <iostream>
namespace notstd // WARNING: at own risk, otherwise use own namespace
{
template <size_t... Ints>
struct index_sequence
{
using type = index_sequence;
using value_type = size_t;
static constexpr std::size_t size() noexcept { return sizeof...(Ints); }
};
// --------------------------------------------------------------
template <class Sequence1, class Sequence2>
struct _merge_and_renumber;
template <size_t... I1, size_t... I2>
struct _merge_and_renumber<index_sequence<I1...>, index_sequence<I2...>>
: index_sequence<I1..., (sizeof...(I1)+I2)...>
{ };
// --------------------------------------------------------------
template <size_t N>
struct make_index_sequence
: _merge_and_renumber<typename make_index_sequence<N/2>::type,
typename make_index_sequence<N - N/2>::type>
{ };
template<> struct make_index_sequence<0> : index_sequence<> { };
template<> struct make_index_sequence<1> : index_sequence<0> { };
template <class T, class Tuple>
struct Index;
template <class T, class... Types>
struct Index<T, std::tuple<T, Types...>> {
static const std::size_t value = 0;
};
template <class T, class U, class... Types>
struct Index<T, std::tuple<U, Types...>> {
static const std::size_t value = 1 + Index<T, std::tuple<Types...>>::value;
};
}
enum class my_tag
{
A,B,C
};
const char* name(my_tag t)
{
switch(t) {
case my_tag ::A:
return "A";
case my_tag ::B:
return "B";
case my_tag ::C:
return "C";
}
return "logic error";
}
template<class TagType, TagType TagValue>
struct tagged_vector : std::vector<int>
{
using std::vector<int>::vector;
};
template<class TagType, TagType...Tags>
struct selection
{
using storage_type = std::tuple<tagged_vector<TagType, Tags>...>;
template<TagType Tag>
void add(int value)
{
using index = notstd::Index<tagged_vector<TagType, Tag>, storage_type>;
std::get<index::value>(storage_).push_back(value);
}
template<std::size_t I>
static const char* make_sep(std::integral_constant<std::size_t, I>) {
return "\n";
}
static const char* make_sep(std::integral_constant<std::size_t, 0>) {
return "";
};
template<TagType Tag>
static void impl_report(std::ostream& os, tagged_vector<TagType, Tag> const& vec, const char* sep)
{
os << sep << name(Tag) << " ";
std::copy(std::begin(vec), std::end(vec), std::ostream_iterator<int>(os, ", "));
}
template<class Tuple, std::size_t...Is>
static void impl_report(std::ostream& os, Tuple&& tup, notstd::index_sequence<Is...>)
{
using expand = int[];
void(expand{0,
(impl_report(os, std::get<Is>(tup), make_sep(std::integral_constant<std::size_t, Is>())), 0)...
});
};
std::ostream& report(std::ostream& os) const {
impl_report(os, storage_, notstd::make_index_sequence<std::tuple_size<storage_type>::value>());
return os;
}
storage_type storage_;
};
int main()
{
auto sel = selection<my_tag, my_tag::A, my_tag::B, my_tag::C>();
sel.add<my_tag::A>(100);
sel.add<my_tag::A>(101);
sel.add<my_tag::B>(90);
sel.add<my_tag ::C>(10);
sel.add<my_tag ::C>(11);
sel.report(std::cout) << std::endl;
}