Intel® C++ Compiler
Community support and assistance for creating C++ code that runs on platforms based on Intel® processors.

bug report, template alias problem

Even_E_
New Contributor I
442 Views

Hello,

I'd like to report a compilation failure for this code (first part is just for C++14 support) :

//////////// NOT INTERESTING PART ///////////////////////

namespace std {

template <typename T, T... Is>
struct integer_sequence
{
    using value_type = T;
    static_assert(std::is_integral<T>::value,
        "std::integer_sequence can only be instantiated with an integral type" );

    static inline size_t size() { return (sizeof...(Is)); }
};

template <size_t... Is>
using index_sequence = integer_sequence<size_t, Is...>;

namespace integer_sequence_detail {

template <typename T, size_t... Extra>
struct repeat;

template <typename T, T... Is, size_t... Extra>
struct repeat<integer_sequence<T, Is...>, Extra...>
{
    using type =  integer_sequence<T, Is...,
        1 * sizeof...(Is) + Is...,
        2 * sizeof...(Is) + Is...,
        3 * sizeof...(Is) + Is...,
        4 * sizeof...(Is) + Is...,
        5 * sizeof...(Is) + Is...,
        6 * sizeof...(Is) + Is...,
        7 * sizeof...(Is) + Is...,
        Extra...>;
};

template <size_t N>
struct parity;

template <size_t N>
struct make
  : parity<N % 8>::template pmake<N> {};

template <> struct make<0> { using type = integer_sequence<size_t>; };
template <> struct make<1> { using type = integer_sequence<size_t, 0>; };
template <> struct make<2> { using type = integer_sequence<size_t, 0, 1>; };
template <> struct make<3> { using type = integer_sequence<size_t, 0, 1, 2>; };
template <> struct make<4> { using type = integer_sequence<size_t, 0, 1, 2, 3>; };
template <> struct make<5> { using type = integer_sequence<size_t, 0, 1, 2, 3, 4>; };
template <> struct make<6> { using type = integer_sequence<size_t, 0, 1, 2, 3, 4, 5>; };
template <> struct make<7> { using type = integer_sequence<size_t, 0, 1, 2, 3, 4, 5, 6>; };

template <> struct parity<0> { template <size_t N> struct pmake : repeat<typename make<N / 8>::type> {}; };
template <> struct parity<1> { template <size_t N> struct pmake : repeat<typename make<N / 8>::type, N - 1> {}; };
template <> struct parity<2> { template <size_t N> struct pmake : repeat<typename make<N / 8>::type, N - 2, N - 1> {}; };
template <> struct parity<3> { template <size_t N> struct pmake : repeat<typename make<N / 8>::type, N - 3, N - 2, N - 1> {}; };
template <> struct parity<4> { template <size_t N> struct pmake : repeat<typename make<N / 8>::type, N - 4, N - 3, N - 2, N - 1> {}; };
template <> struct parity<5> { template <size_t N> struct pmake : repeat<typename make<N / 8>::type, N - 5, N - 4, N - 3, N - 2, N - 1> {}; };
template <> struct parity<6> { template <size_t N> struct pmake : repeat<typename make<N / 8>::type, N - 6, N - 5, N - 4, N - 3, N - 2, N - 1> {}; };
template <> struct parity<7> { template <size_t N> struct pmake : repeat<typename make<N / 8>::type, N - 7, N - 6, N - 5, N - 4, N - 3, N - 2, N - 1> {}; };

template <typename T, typename U>
struct convert
{
    template <typename>
    struct result;

    template <T ...Is>
    struct result<integer_sequence<T, Is...>>
    {
        using type = integer_sequence<U, Is...>;
    };
};

template <typename T>
struct convert<T, T>
{
    template <typename U>
    struct result
    {
        using type = U;
    };
};

template <typename T, T N>
using make_integer_sequence_unchecked =
    typename convert<size_t, T>::template result<typename make<N>::type>::type;
 
template <typename T, T N>
struct make_integer_sequence
{
    static_assert(std::is_integral<T>::value,
        "std::make_integer_sequence can only be instantiated with an integral type");
    static_assert(0 <= N, "std::make_integer_sequence input shall not be negative");
 
    using type = make_integer_sequence_unchecked<T, N>;
};

} // namespace integer_sequence_detail

template <typename T, T N>
using make_integer_sequence = typename integer_sequence_detail::make_integer_sequence<T, N>::type;

template <size_t N>
using make_index_sequence = make_integer_sequence<size_t, N>;

template <typename... T>
using index_sequence_for = make_index_sequence<sizeof...(T)>;

} // namespace std

//////////// INTERESTING PART ///////////////////////

template <size_t dim>
struct vec
{
	float va[dim];
	
	explicit constexpr vec(const float& value) noexcept
      : vec(std::make_index_sequence<dim>(), value) {}
protected:
    //! Expanding constructor repeating the same scalar value.
    template <size_t... Is>
    inline constexpr vec(std::index_sequence<Is...>, const float& value) noexcept
      : va{(void(Is), value)...} {}
      
};

int main(void)
{
    vec<2> a(0.0f);
}

The output is :

main.cpp(301): error : no instance of constructor "vec<dim>::vec [with dim=2Ui64]" matches the argument list
1>              argument types are: (std::make_index_sequence<2Ui64>, const float)
1>          : vec(std::make_index_sequence<dim>(), value) {}
1>               ^
1>            detected during instantiation of "vec<dim>::vec(const float &) [with dim=2Ui64]" at line 312
1>  
1>main.cpp(312): error : assertion failed at: "shared/cfe/edgcpfe/exprutil.c", line 14888
1>  
1>        vec<2> a(0.0f);

Thanks for your answers.

0 Kudos
2 Replies
Even_E_
New Contributor I
442 Views

Hi, since the post stayed as a draft for 2 days I tried ICC 2015 beta and the bug is fixed.

The workaround for this special case (with 14.0.2) is to replace "index_sequence<" by "integer_sequence<size_t, " line 124.

Thx for the fix in the 2015 version !!

0 Kudos
KitturGanesh
Employee
442 Views

Great, was about to test it out with 15.0 myself when I saw your response Even. Thanks for letting us know :-)

_Kittur

0 Kudos
Reply