c++ - C++中可能进行以下编译时编程任务

标签 c++ templates

template<std::size_t ENUM>
struct createP2E
{    static constexpr std::size_t SIZE = 1;
     static constexpr std::size_t P2E[SIZE] = {ENUM};
};

template<typename A, typename B>
struct combine;

template<>
struct combine<createP2E<2>, createP2E<3> >
{       static constexpr std::size_t SIZE = 2;
        static constexpr std::size_t P2E[2] = {2, 3};
        typedef combine type;
};
template<typename A>
struct combine<A, A>
{       typedef A type;
};

是否可以让编译器创建组合?
是的,我希望创建数组。
更多信息:
createP2E的参数(枚举的位置)是一个枚举。
创建的数组P2E应该包含按排序顺序的枚举。

事后编辑:

我可能不清楚我的问题:

我想通过使用constexpr而不是boost::mpl::set或boost::mp11::list <>的元编程来合并两个提供的集合。结果集应该再次可以用于合并。

最佳答案

我想可以做到的。正如您已经说过的,这里的核心问题是将一个数组追加到另一个数组然后对其进行排序。这是基于c++ 17 解决此问题的方法。不幸的是,它使用std::arrays而不是c数组。

我只是简单地将这个answer和这个code结合在一起就可以得到(满分功)

#include <iostream>
#include <array>

namespace detail
{
template<std::size_t ... Size>
struct num_tuple
{

};

template<std::size_t Prepend, typename T>
struct appender {};

template<std::size_t Prepend, std::size_t ... Sizes>
struct appender<Prepend, num_tuple<Sizes...>>
{
    using type = num_tuple<Prepend, Sizes...>;
};

template<std::size_t Size, std::size_t Counter = 0>
struct counter_tuple
{
    using type = typename appender<Counter, typename counter_tuple<Size, Counter+1>::type>::type;
};


template<std::size_t Size>
struct counter_tuple<Size, Size>
{
    using type = num_tuple<>;
};

}


template<typename T, std::size_t LL, std::size_t RL, std::size_t ... LLs, std::size_t ... RLs>
constexpr std::array<T, LL+RL> join(const std::array<T, LL> rhs, const std::array<T, RL> lhs, detail::num_tuple<LLs...>, detail::num_tuple<RLs...>)
{
    return {rhs[LLs]..., lhs[RLs]... };
};


template<typename T, std::size_t LL, std::size_t RL>
constexpr std::array<T, LL+RL> join(std::array<T, LL> rhs, std::array<T, RL> lhs)
{
    //using l_t = typename detail::counter_tuple<LL>::type;
    return join(rhs, lhs, typename detail::counter_tuple<LL>::type(), typename detail::counter_tuple<RL>::type());
}


template<typename Array>
constexpr void comb_sort_impl ( Array & array_ ) noexcept {
    using size_type = typename Array::size_type;
    size_type gap = array_.size ( );
    bool swapped = false;
    while ( ( gap > size_type { 1 } ) or swapped ) {
        if ( gap > size_type { 1 } ) {
            gap = static_cast<size_type> ( gap / 1.247330950103979 );
        }
        swapped = false;
        for ( size_type i = size_type { 0 }; gap + i < static_cast<size_type> ( array_.size ( ) ); ++i ) {
            if ( array_ [ i ] > array_ [ i + gap ] ) {
                auto swap = array_ [ i ];
                array_ [ i ] = array_ [ i + gap ];
                array_ [ i + gap ] = swap;
                swapped = true;
            }
        }
    }
}

template<typename Array>
constexpr Array sort ( Array array_ ) noexcept {
    auto sorted = array_;
    comb_sort_impl ( sorted );
    return sorted;
}


struct
arr1
{
    static constexpr auto values = std::array<int, 9> { 6, 8, 0, 1, 1, 22, 9, 2, 7 };
};

struct
arr2
{
    static constexpr auto values = std::array<int,3>{0,12,5};
};

struct
sorted 
{
    static constexpr auto values 
        = sort ( join(arr1::values,arr2::values) );
};

int main ( ) {

    for ( auto i : sorted::values )
        std::cout << i << ' ';
    std::cout << std::endl;

    return EXIT_SUCCESS;
}

这是live demo

备注:如果Combine将始终只合并两个存储一个元素的createP2E,则可能有更简单的解决方案。但是,这种通用方法允许您组合两个combine对象。但是,您需要添加一些功能,以从组合数组中删除重复项以具有正确的枚举。

更新这是一个解决方案,它返回已排序的数组,其中删除了重复项。这不是很好,但是可以完成工作(live demo):
#include <iostream>
#include <array>

namespace detail
{
template<std::size_t ... Size>
struct num_tuple
{

};

template<std::size_t Prepend, typename T>
struct appender {};

template<std::size_t Prepend, std::size_t ... Sizes>
struct appender<Prepend, num_tuple<Sizes...>>
{
    using type = num_tuple<Prepend, Sizes...>;
};

template<std::size_t Size, std::size_t Counter = 0>
struct counter_tuple
{
    using type = typename appender<Counter, typename counter_tuple<Size, Counter+1>::type>::type;
};


template<std::size_t Size>
struct counter_tuple<Size, Size>
{
    using type = num_tuple<>;
};

}


template<typename T, std::size_t LL, std::size_t RL, std::size_t ... LLs, std::size_t ... RLs>
constexpr std::array<T, LL+RL> join(const std::array<T, LL> rhs, const std::array<T, RL> lhs, detail::num_tuple<LLs...>, detail::num_tuple<RLs...>)
{
    return {rhs[LLs]..., lhs[RLs]... };
};


template<typename T, std::size_t LL, std::size_t RL>
constexpr std::array<T, LL+RL> join(std::array<T, LL> rhs, std::array<T, RL> lhs)
{
    //using l_t = typename detail::counter_tuple<LL>::type;
    return join(rhs, lhs, typename detail::counter_tuple<LL>::type(), typename detail::counter_tuple<RL>::type());
}


template<typename Array>
constexpr void comb_sort_impl ( Array & array_ ) noexcept {
    using size_type = typename Array::size_type;
    size_type gap = array_.size ( );
    bool swapped = false;
    while ( ( gap > size_type { 1 } ) or swapped ) {
        if ( gap > size_type { 1 } ) {
            gap = static_cast<size_type> ( gap / 1.247330950103979 );
        }
        swapped = false;
        for ( size_type i = size_type { 0 }; gap + i < static_cast<size_type> ( array_.size ( ) ); ++i ) {
            if ( array_ [ i ] > array_ [ i + gap ] ) {
                auto swap = array_ [ i ];
                array_ [ i ] = array_ [ i + gap ];
                array_ [ i + gap ] = swap;
                swapped = true;
            }
        }
    }
}






template<typename Array>
constexpr Array sort ( Array array_ ) noexcept {
    auto sorted = array_;
    comb_sort_impl ( sorted );
    return sorted;
}


struct
arr1
{
    static constexpr auto values = std::array<int, 9> { 6, 8, 0, 1, 1, 22, 9, 2, 7 };
};

struct
arr2
{
    static constexpr auto values = std::array<int,3>{0,12,5};
};

struct
sorted 
{
    static constexpr auto values 
        = sort ( join(arr1::values,arr2::values) );
};

template <typename T, std::size_t N>
constexpr auto size_without_duplicates (const std::array<T,N> &array_)
{
    std::array<T,N> ret = {};
    std::size_t count = 1; 
    ret[0] = array_[0];
    for (unsigned int i = 1; i < N; ++i)
        if (array_[i-1] != array_[i])
            ++count;

    return count;
}


template <class T>
constexpr auto remove_duplicates ()
{
    std::array<int,size_without_duplicates(T::values)> ret = {};
    unsigned int count = 0; 
    ret[0] = T::values[0];
    for (unsigned int i = 1; i < T::values.size(); ++i)
        if (T::values[i-1] != T::values[i])
        {
            ret[++count] = T::values[i];
        }

    return ret;
}


struct myset
{
    static constexpr auto values = remove_duplicates<sorted>();
};

int main ( ) {


    for ( auto i : sorted::values )
        std::cout << i << ' ';

    std::cout << std::endl;

    for ( auto i : myset::values )
        std::cout << i << ' ';
    std::cout << std::endl;

    return EXIT_SUCCESS;
}

关于c++ - C++中可能进行以下编译时编程任务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61787089/

相关文章:

c++ - 模板中的未知返回类型

c++ - 构建应用程序时出现 undefined reference 错误;

c++ - 有状态的元编程是病态的(还)吗?

c++ - 派生到基隐式指针类型转换

asp.net-mvc - 使用 ASP.NET MVC 作为电子邮件模板引擎 : Good Idea?

c++ - 混合运行时/编译时条件下的标签调度

c++ - 无法使 MySQL 连接器/C++ 工作 - 未处理的异常 (sql::SQLException) Visual Studio 2010

C++ - 为离线 VS2013 加载 Microsoft 符号

c++ - 在 "char type"模板类中使用字符串文字

c++ - 如何避免使用模板类型的派生类在多态性中进行动态转换