Search code examples
c++copy-constructorconversion-operator

Why is copy-ctor called instead of implicit conversion operator when using variadic arguments


I have following code:

#include <iostream>

class Dog
{
public:
    Dog() : ptr(nullptr)
    {
        std::cout << "ctor" << std::endl;
    }

    Dog(const Dog&) = delete;
    Dog(Dog&&) = delete;

    inline operator void*() const
    {
        std::cout << "conversion op" << std::endl;
        return ptr;
    }

private:
    void* ptr;
};

void dosomething_buf(void*)
{

}

void dosomething(const Dog& d)
{
    dosomething_buf(d);
}

int main()
{
    Dog d;
    dosomething(d);
}

This code works as intended and calls ctor and implicit conversion operator once.

However if I change the signature of dosomething_buf(void*) to void dosomething_buf(...);

I get following compile-error:

[build] [ 50%] Building CXX object CMakeFiles/playground.dir/test.cpp.o
[build] /media/rbs42/data/Gebos/RBS42/PlayGround/test.cpp: In function ‘void dosomething(const Dog&)’:
[build] /media/rbs42/data/Gebos/RBS42/PlayGround/test.cpp:31:20: error: use of deleted function ‘Dog::Dog(const Dog&)’
[build]      dosomething_buf(d);
[build]                     ^
[build] /media/rbs42/data/Gebos/RBS42/PlayGround/test.cpp:11:5: note: declared here
[build]      Dog(const Dog&) = delete;
[build]      ^~~

Why does the compiler call the copy-ctor?


Solution

  • Why would you expect the void* conversion operator to be invoked at all, since there's no void* argument anymore?

    C-style variadic functions (which, by they way, are not recommended in C++ since we have varadic templates) take an arbitrary number of arguments by value. When calling dosomething_buf(d), you're copying d to initialize one of the variadic arguments.