constexpr to concatenate two or more char strings

前端 未结 1 478
庸人自扰
庸人自扰 2020-12-14 19:14

I\'m trying to make a constexpr function that will concatenate an arbitrary number of char arrays by working from the following answer by Xeo, which concatenates two char ar

相关标签:
1条回答
  • 2020-12-14 20:08
    template<size_t S>
    using size=std::integral_constant<size_t, S>;
    
    template<class T, size_t N>
    constexpr size<N> length( T const(&)[N] ) { return {}; }
    template<class T, size_t N>
    constexpr size<N> length( std::array<T, N> const& ) { return {}; }
    
    template<class T>
    using length_t = decltype(length(std::declval<T>()));
    constexpr size_t sum_string_sizes() { return 0; }
    template<class...Ts>
    constexpr size_t sum_string_sizes( size_t i, Ts... ts ) {
      return (i?i-1:0) + sum_sizes(ts...);
    }
    

    then

    template
    template<unsigned N1, unsigned N2, class... Us>
    constexpr auto
    concat(const char(&a1)[N1], const char(&a2)[N2], const Us&... xs)
    -> std::array<char, sum_string_sizes( N1, N2, length_t<Us>::value... )+1 >
    {
      return concat(a1, concat(a2, xs...));
    }
    

    which gets rid of the recursion-in-decltype.


    Here is a full example using the above approach:

    template<size_t S>
    using size=std::integral_constant<size_t, S>;
    
    template<class T, size_t N>
    constexpr size<N> length( T const(&)[N] ) { return {}; }
    template<class T, size_t N>
    constexpr size<N> length( std::array<T, N> const& ) { return {}; }
    
    template<class T>
    using length_t = decltype(length(std::declval<T>()));
    
    constexpr size_t string_size() { return 0; }
    template<class...Ts>
    constexpr size_t string_size( size_t i, Ts... ts ) {
      return (i?i-1:0) + string_size(ts...);
    }
    template<class...Ts>
    using string_length=size< string_size( length_t<Ts>{}... )>;
    
    template<class...Ts>
    using combined_string = std::array<char, string_length<Ts...>{}+1>;
    
    template<class Lhs, class Rhs, unsigned...I1, unsigned...I2>
    constexpr const combined_string<Lhs,Rhs>
    concat_impl( Lhs const& lhs, Rhs const& rhs, seq<I1...>, seq<I2...>)
    {
      // the '\0' adds to symmetry:
      return {{ lhs[I1]..., rhs[I2]..., '\0' }};
    }
    
    template<class Lhs, class Rhs>
    constexpr const combined_string<Lhs,Rhs>
    concat(Lhs const& lhs, Rhs const& rhs)
    {
      return concat_impl(
        lhs, rhs,
        gen_seq<string_length<Lhs>{}>{},
        gen_seq<string_length<Rhs>{}>{}
     );
    }
    
    template<class T0, class T1, class... Ts>
    constexpr const combined_string<T0, T1, Ts...>
    concat(T0 const&t0, T1 const&t1, Ts const&...ts)
    {
      return concat(t0, concat(t1, ts...));
    }
    
    template<class T>
    constexpr const combined_string<T>
    concat(T const&t) {
      return concat(t, "");
    }
    constexpr const combined_string<>
    concat() {
      return concat("");
    }
    

    live example

    0 讨论(0)
提交回复
热议问题