https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78846
Bug ID: 78846 Summary: std1y compiler infinite output Product: gcc Version: 6.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: k...@st-andrews.ac.uk Target Milestone: --- Created attachment 40358 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=40358&action=edit .ii file I created a c++14 program to implement lazy evaluation, but the compiler seems to be producing infinite output. Machine (1) System: Darwin 13.4.0 x86_64 i386 G++: g++-6 (Homebrew gcc 6.2.0) 6.2.0 Command: g++-6 -std=c++1y binary_operation.cpp Machine (2) System: Linux 4.4.0-53-generic x86_64 x86_64 x86_64 GNU/Linux G++: g++ (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609 Command: g++ -std=c++1y binary_operation.cpp (Actually, trying to compile with clang produces the same result). For preprocessed file, see the attachment. CODE -------------------------------------------------- #include <iostream> static const auto add = [](auto a, auto b) {return a + b;}; static const auto sub = [](auto a, auto b) {return a - b;}; static const auto mul = [](auto a, auto b) {return a * b;}; static const auto frac = [](auto a, auto b) {return a / b;}; template <class A, class B, class F> class BinaryOP; template <class A, class B> using Addition = BinaryOP <A, B, decltype(add)>; template <class A, class B> using Subtraction = BinaryOP <A, B, decltype(sub)>; template <class A, class B> using Multiplication = BinaryOP <A, B, decltype(mul)>; template <class A, class B> using Division = BinaryOP <A, B, decltype(frac)>; static const auto make_binop = [](auto a, auto b, auto F) { return BinaryOP<decltype(a), decltype(b), decltype(F)>(a, b, F); }; static const auto make_add = [](auto a, auto b) { return make_binop(a, b, add); }; static const auto make_sub = [](auto a, auto b) { return Subtraction<decltype(a), decltype(b)>(a, b, sub); }; static const auto make_mul = [](auto a, auto b) { return Multiplication<decltype(a), decltype(b)>(a, b, mul); }; static const auto make_div = [](auto a, auto b) { return Division<decltype(a), decltype(b)>(a, b, frac); }; template <class A, class B, class F> class BinaryOP { protected: typedef BinaryOP <A, B, F> THIS_T; A lhs; B rhs; F func; public: BinaryOP(A lhs, B rhs, F &func): lhs(lhs), rhs(rhs), func(func) {} virtual ~BinaryOP() {} template <class T> operator T() { return func(T(lhs), T(rhs)); } template <class T> Addition<THIS_T, T> operator+(const T &other) { return make_add(*this, other); } template <class T> Subtraction<THIS_T, T> operator-(const T &other) { return make_sub(*this, other); } template <class T> Multiplication<THIS_T, T> operator*(const T &other) { return make_mul(*this, other); } template <class T> Division<THIS_T, T> operator/(const T &other) { return make_div(*this, other); } friend std::ostream &operator<<(std::ostream &os, const THIS_T &bin) { os << "(binop: " << bin.lhs << ", " << bin.rhs << ")"; return os; } }; int main() { std::cout << make_add(2, 3) + make_sub(5, 6) * make_add(3, 0) << std::endl; } -------------------------------------------------- The problem appeared when I changed: static const auto make_add = [](auto a, auto b) { return Addition<decltype(A), decltype(B), decltype(add)>(a, b, add); }; into static const auto make_add = [](auto a, auto b) { return make_binop(a, b, add); }; OUTPUT (first few lines): -------------------------------------------------- binary_operator.cpp: In instantiation of 'BinaryOP<A, B, F>::operator T() [with T = BinaryOP<BinaryOP<int, int, <lambda(auto:1, auto:2)> >, BinaryOP<BinaryOP<int, int, const<lambda(auto:3, auto:4)> >, BinaryOP<int, int, <lambda(auto:1, auto:2)> >, const<lambda(auto:5, auto:6)> >, const<lambda(auto:1, auto:2)> >; A = int; B = int; F = <lambda(auto:1, auto:2)>]': binary_operator.cpp:47:17: required from 'BinaryOP<A, B, F>::operator T() [with T = BinaryOP<BinaryOP<int, int, <lambda(auto:1, auto:2)> >, BinaryOP<BinaryOP<int, int, const<lambda(auto:3, auto:4)> >, BinaryOP<int, int, <lambda(auto:1, auto:2)> >, const<lambda(auto:5, auto:6)> >, const<lambda(auto:1, auto:2)> >; A = BinaryOP<int, int, <lambda(auto:1, auto:2)> >; B = BinaryOP<BinaryOP<int, int, const<lambda(auto:3, auto:4)> >, BinaryOP<int, int, <lambda(auto:1, auto:2)> >, const<lambda(auto:5, auto:6)> >; F = <lambda(auto:1, auto:2)>]' binary_operator.cpp:51:33: required from 'Addition<BinaryOP<A, B, F>, T> BinaryOP<A, B, F>::operator+(const T&) [with T = BinaryOP<BinaryOP<int, int, const<lambda(auto:3, auto:4)> >, BinaryOP<int, int, <lambda(auto:1, auto:2)> >, const<lambda(auto:5, auto:6)> >; A = int; B = int; F = <lambda(auto:1, auto:2)>; Addition<BinaryOP<A, B, F>, T> = BinaryOP<BinaryOP<int, int, <lambda(auto:1, auto:2)> >, BinaryOP<BinaryOP<int, int, const<lambda(auto:3, auto:4)> >, BinaryOP<int, int, <lambda(auto:1, auto:2)> >, const<lambda(auto:5, auto:6)> >, const<lambda(auto:1, auto:2)> >]' binary_operator.cpp:73:63: required from here binary_operator.cpp:47:17: error: no matching function for call to 'BinaryOP<BinaryOP<int, int, <lambda(auto:1, auto:2)> >, BinaryOP<BinaryOP<int, int, const<lambda(auto:3, auto:4)> >, BinaryOP<int, int, <lambda(auto:1, auto:2)> >, const<lambda(auto:5, auto:6)> >, const<lambda(auto:1, auto:2)> >::BinaryOP(int&)' return func(T(lhs), T(rhs)); ^~~~~~ binary_operator.cpp:35:3: note: candidate: BinaryOP<A, B, F>::BinaryOP(A, B, F) [with A = BinaryOP<int, int, <lambda(auto:1, auto:2)> >; B = BinaryOP<BinaryOP<int, int, const<lambda(auto:3, auto:4)> >, BinaryOP<int, int, <lambda(auto:1, auto:2)> >, const<lambda(auto:5, auto:6)> >; F = const<lambda(auto:1, auto:2)>] BinaryOP(A lhs, B rhs, F func): ^~~~~~~~ binary_operator.cpp:35:3: note: candidate expects 3 arguments, 1 provided binary_operator.cpp:22:7: note: candidate: constexpr BinaryOP<BinaryOP<int, int, <lambda(auto:1, auto:2)> >, BinaryOP<BinaryOP<int, int, const<lambda(auto:3, auto:4)> >, BinaryOP<int, int, <lambda(auto:1, auto:2)> >, const<lambda(auto:5, auto:6)> >, const<lambda(auto:1, auto:2)> >::BinaryOP(const BinaryOP<BinaryOP<int, int, <lambda(auto:1, auto:2)> >, BinaryOP<BinaryOP<int, int, const<lambda(auto:3, auto:4)> >, BinaryOP<int, int, <lambda(auto:1, auto:2)> >, const<lambda(auto:5, auto:6)> >, const<lambda(auto:1, auto:2)> >&) class BinaryOP { ^~~~~~~~ binary_operator.cpp:22:7: note: no known conversion for argument 1 from 'int' to 'const BinaryOP<BinaryOP<int, int, <lambda(auto:1, auto:2)> >, BinaryOP<BinaryOP<int, int, const<lambda(auto:3, auto:4)> >, BinaryOP<int, int, <lambda(auto:1, auto:2)> >, const<lambda(auto:5, auto:6)> >, const<lambda(auto:1, auto:2)> >&' binary_operator.cpp:47:25: error: no matching function for call to 'BinaryOP<BinaryOP<int, int, <lambda(auto:1, auto:2)> >, BinaryOP<BinaryOP<int, int, const<lambda(auto:3, auto:4)> >, BinaryOP<int, int, <lambda(auto:1, auto:2)> >, const<lambda(auto:5, auto:6)> >, const<lambda(auto:1, auto:2)> >::BinaryOP(int&)' return func(T(lhs), T(rhs)); ^~~~~~ binary_operator.cpp:35:3: note: candidate: BinaryOP<A, B, F>::BinaryOP(A, B, F) [with A = BinaryOP<int, int, <lambda(auto:1, auto:2)> >; B = BinaryOP<BinaryOP<int, int, const<lambda(auto:3, auto:4)> >, BinaryOP<int, int, <lambda(auto:1, auto:2)> >, const<lambda(auto:5, auto:6)> >; F = const<lambda(auto:1, auto:2)>] BinaryOP(A lhs, B rhs, F func): ^~~~~~~~ binary_operator.cpp:35:3: note: candidate expects 3 arguments, 1 provided binary_operator.cpp:22:7: note: candidate: constexpr BinaryOP<BinaryOP<int, int, <lambda(auto:1, auto:2)> >, BinaryOP<BinaryOP<int, int, const<lambda(auto:3, auto:4)> >, BinaryOP<int, int, <lambda(auto:1, auto:2)> >, const<lambda(auto:5, auto:6)> >, const<lambda(auto:1, auto:2)> >::BinaryOP(const BinaryOP<BinaryOP<int, int, <lambda(auto:1, auto:2)> >, BinaryOP<BinaryOP<int, int, const<lambda(auto:3, auto:4)> >, BinaryOP<int, int, <lambda(auto:1, auto:2)> >, const<lambda(auto:5, auto:6)> >, const<lambda(auto:1, auto:2)> >&) class BinaryOP { ^~~~~~~~ binary_operator.cpp:22:7: note: no known conversion for argument 1 from 'int' to 'const BinaryOP<BinaryOP<int, int, <lambda(auto:1, auto:2)> >, BinaryOP<BinaryOP<int, int, const<lambda(auto:3, auto:4)> >, BinaryOP<int, int, <lambda(auto:1, auto:2)> >, const<lambda(auto:5, auto:6)> >, const<lambda(auto:1, auto:2)> >&' binary_operator.cpp: In instantiation of 'BinaryOP<A, B, F>::operator T() [with T = BinaryOP<BinaryOP<int, int, <lambda(auto:1, auto:2)> >, BinaryOP<BinaryOP<int, int, const<lambda(auto:3, auto:4)> >, BinaryOP<int, int, <lambda(auto:1, auto:2)> >, const<lambda(auto:5, auto:6)> >, const<lambda(auto:1, auto:2)> >; A = int; B = int; F = const<lambda(auto:3, auto:4)>]': binary_operator.cpp:47:17: required from 'BinaryOP<A, B, F>::operator T() [with T = BinaryOP<BinaryOP<int, int, <lambda(auto:1, auto:2)> >, BinaryOP<BinaryOP<int, int, const<lambda(auto:3, auto:4)> >, BinaryOP<int, int, <lambda(auto:1, auto:2)> >, const<lambda(auto:5, auto:6)> >, const<lambda(auto:1, auto:2)> >; A = BinaryOP<int, int, const<lambda(auto:3, auto:4)> >; B = BinaryOP<int, int, <lambda(auto:1, auto:2)> >; F = const<lambda(auto:5, auto:6)>]' binary_operator.cpp:47:25: required from 'BinaryOP<A, B, F>::operator T() [with T = BinaryOP<BinaryOP<int, int, <lambda(auto:1, auto:2)> >, BinaryOP<BinaryOP<int, int, const<lambda(auto:3, auto:4)> >, BinaryOP<int, int, <lambda(auto:1, auto:2)> >, const<lambda(auto:5, auto:6)> >, const<lambda(auto:1, auto:2)> >; A = BinaryOP<int, int, <lambda(auto:1, auto:2)> >; B = BinaryOP<BinaryOP<int, int, const<lambda(auto:3, auto:4)> >, BinaryOP<int, int, <lambda(auto:1, auto:2)> >, const<lambda(auto:5, auto:6)> >; F = <lambda(auto:1, auto:2)>]' binary_operator.cpp:51:33: required from 'Addition<BinaryOP<A, B, F>, T> BinaryOP<A, B, F>::operator+(const T&) [with T = BinaryOP<BinaryOP<int, int, const<lambda(auto:3, auto:4)> >, BinaryOP<int, int, <lambda(auto:1, auto:2)> >, const<lambda(auto:5, auto:6)> >; A = int; B = int; F = <lambda(auto:1, auto:2)>; Addition<BinaryOP<A, B, F>, T> = BinaryOP<BinaryOP<int, int, <lambda(auto:1, auto:2)> >, BinaryOP<BinaryOP<int, int, const<lambda(auto:3, auto:4)> >, BinaryOP<int, int, <lambda(auto:1, auto:2)> >, const<lambda(auto:5, auto:6)> >, const<lambda(auto:1, auto:2)> >]' binary_operator.cpp:73:63: required from here binary_operator.cpp:47:17: error: no matching function for call to 'BinaryOP<BinaryOP<int, int, <lambda(auto:1, auto:2)> >, BinaryOP<BinaryOP<int, int, const<lambda(auto:3, auto:4)> >, BinaryOP<int, int, <lambda(auto:1, auto:2)> >, const<lambda(auto:5, auto:6)> >, const<lambda(auto:1, auto:2)> >::BinaryOP(int&)' return func(T(lhs), T(rhs)); ^~~~~~ binary_operator.cpp:35:3: note: candidate: BinaryOP<A, B, F>::BinaryOP(A, B, F) [with A = BinaryOP<int, int, <lambda(auto:1, auto:2)> >; B = BinaryOP<BinaryOP<int, int, const<lambda(auto:3, auto:4)> >, BinaryOP<int, int, <lambda(auto:1, auto:2)> >, const<lambda(auto:5, auto:6)> >; F = const<lambda(auto:1, auto:2)>] BinaryOP(A lhs, B rhs, F func): ^~~~~~~~ ... --------------------------------------------------