https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94888
Jonathan Wakely <redi at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|WAITING |RESOLVED Resolution|--- |INVALID --- Comment #4 from Jonathan Wakely <redi at gcc dot gnu.org> --- Reduced: //RemoveRef template<typename _Tp> struct RemoveRef { typedef _Tp type; }; template<typename _Tp> struct RemoveRef<_Tp&> { typedef _Tp type; }; template<typename _Tp> struct RemoveRef<_Tp&&> { typedef _Tp type; }; //Forward template<typename _Tp> _Tp&& Forward(typename RemoveRef<_Tp>::type& __t) { return static_cast<_Tp&&>(__t); } template<typename _Tp> _Tp&& Forward(typename RemoveRef<_Tp>::type&& __t) { return static_cast<_Tp&&>(__t); } template <typename T> struct FunctionImpl { template <typename Ty> FunctionImpl(Ty&& t_) : t(Forward<Ty>(t_)) {} T t; }; struct FunctionBridger { template <typename T> FunctionBridger(T&& func_) { delete new FunctionImpl<typename RemoveRef<T>::type>(Forward<T>(func_) ); } }; struct Function : public FunctionBridger { template <typename Ty> Function( Ty&& func) : FunctionBridger(Forward<Ty>(func)) { } ~Function() {} }; void f() { } int main() { Function func = &f; } The variable definition in main() uses copy-initialization, so it first creates a temporary of type Function, then it copies it. The copy uses the Function(Ty&&) constructor recursively, until it overflows the stack. Clang behaves the same if you use -fno-elide-constructors Your code is invalid, because it assumes that copy elision happens, which is not guaranteed in C++14. For C++17 it works correctly. I'm not sure *why* G++ doesn't elide the copy, as it usually does do that even in C++14. But it's not required to do so before C++17, so this isn't a bug. If you remove the ~Function() destructor then G++ does elide the copy. You could also constrain the Function(Ty&&) constructor so it will not be used to copy/move an object of the same type.