Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/130.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 结构的编译时枚举映射_C++_Templates_Template Meta Programming - Fatal编程技术网

C++ 结构的编译时枚举映射

C++ 结构的编译时枚举映射,c++,templates,template-meta-programming,C++,Templates,Template Meta Programming,我试图在编译时创建一个基于一些枚举值的结构。我将编写代码,更容易解释: 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:

我试图在编译时创建一个基于一些枚举值的结构。我将编写代码,更容易解释:

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;
}

有没有办法让你编译这段代码?或者一些解决方法来实现相同的行为?可能是所有的枚举?

我不太清楚,但我想你想要的是这样的:

#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;
}
标记是类型还是枚举可能并不重要,但如果您可以使用类型,那么使用类型将使您的生活更轻松

更新:

使用枚举重新实现。请注意,它不太整洁,需要用户更多的知识。这在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可怕性更新:


假设VecStruct只接受一个枚举值,那么VecStruct映射器是什么;应该做什么?VecStruct是一种具有许多其他函数成员和特定于该枚举值的数据的结构。Mapper是一种具有其他更通用功能的管理器,例如,在所有内部结构中查找值。难道你不想要一个元组吗?@RichardHodges tuple是不够的,因为我想使用get而不是get非常有趣的解决方案!是的,我使用的是枚举,所以我必须稍微修改一下,使它能够与它们一起工作。性能如何?@user3770392编译时就解决了。当编译时打开优化功能,将不会有性能开销。这太棒了。。最后一个问题:在我的例子中,为枚举实现这一点,是否可以执行以下操作:使用storage_type=std::tuple?例如,如果我使用5个枚举值,这会创建一个由5个映射器组成的元组吗?是的,除了EnumType可能是类模板参数,而不是存储类型中的模板参数,因为它已经存在implied@user3770392为完整起见,答案更新为使用枚举。请注意更复杂的构造函数以及需要一个自由函数来命名标记值。
#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;

}
#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;

}