Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unexpected infinite recursion in C++ constructors [duplicate]

A minimal example is:

#include <vector>

class A {
private:
    // where the real initialization happens
    void constructor_impl(int);
    void constructor_impl(const A&);

public:
    A(const auto&... args) {
        (constructor_impl(args), ...);
    }
};

int main() {
    A{0, A{1, 2}}; // correct construction
    A{""}; // wrong construction: compiles to an infinite recursion
}

I expect the wrong call A{""} to raise a compile error. But instead the compiler tries to cast "" to A and generates an infinite recursion. GCC, Clang and MSVC generates similar results, so it's unlikely to be a compiler bug.

Why does it happen? How can I refactor my code to avoid this issue?

like image 964
AlumKal Avatar asked Apr 30 '26 15:04

AlumKal


1 Answers

Your templated constructor is effectively a single argument constructor which accepts arguments of any type, therefore any type is implicitly convertible to A. Therefore when A is passed any argument which isn't int or A the compiler will attempt to call void constructor_impl(const A&); via an implicit conversion. As you say this leads to infinite recursion.

To avoid this problem you should mark the constructor as explicit:

explicit A(const auto&... args) {

This will prevent any implicit conversions to A and give you the compiler error you expect. In general, all single argument constructors should be marked explicit to avoid surprising implicit conversions.

like image 58
Alan Birtles Avatar answered May 03 '26 04:05

Alan Birtles



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!