https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93275

            Bug ID: 93275
           Summary: Error when calculating template parameters in
                    recursive template function call
           Product: gcc
           Version: 9.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: tahasuf at gmail dot com
  Target Milestone: ---

Clang and GCC 8 can compile the code without any errors. But GCC 9 gives an
error.


#include <algorithm>
#include <array>
#include <iostream>

namespace math {

        /** forward declaration **/
        template <typename T, std::size_t N>
        struct array;

        /** is_array **/
        template <typename T>
        struct is_array: std::false_type {};

        template <typename T, std::size_t N>
        struct is_array<array<T, N>>: std::true_type {};

        template <typename T>
        inline constexpr bool is_array_v = is_array<T>::value;

        /** array_depth **/
        template <typename T>
        struct array_depth: std::integral_constant<std::size_t, 0> {};

        template <typename T, std::size_t N>
        struct array_depth<array<T, N>>:
                std::integral_constant<std::size_t, 1 + array_depth<T>::value>
{};

        template <typename T>
        inline constexpr bool array_depth_v = array_depth<T>::value;

        /** array **/
        template <typename T, std::size_t N>
        struct array: std::array<T, N> {

                constexpr array operator * (const array& other) const {
                        array result {};
                        std::transform(
                                std::begin(*this),
                                std::end(*this),
                                std::begin(other),
                                std::begin(result),
                                std::multiplies<T>());
                        return result;
                }

                template <typename Other, std::enable_if_t<
                        (array_depth_v<array> > array_depth_v<Other>),
                        std::nullptr_t> = nullptr>
                constexpr array operator * (const Other& other) const {
                        array result {};
                        std::transform(
                                std::begin(*this),
                                std::end(*this),
                                std::begin(result),
                                [other](const T& t) { return t * other; });
                        return result;
                }

                friend std::ostream&
                operator << (std::ostream& out, const array& source) {
                        out << "<array" << N;
                        if constexpr (!is_array_v<T>)
                                out << typeid(T).name();
                        for (auto it: source) {
                                if constexpr (!is_array_v<T>)
                                        out << " ";
                                out << it;
                        }
                        out << ">";
                        return out;
                }
        };
}

int main() {
        math::array<math::array<float, 4>, 1> a0
                {{math::array<float, 4>{{1.f, 2.f, 3.f, 4.f}}}};
        std::cout << a0 * 4.f << std::endl;
        return 0;
}

Reply via email to