Question

I have a helper class for freeing MYSQL_RES handles.

class auto_mysqlres
{
public:
  auto_mysqlres(MYSQL_RES *res) : m_res(res)
  {
  }

  ~auto_mysqlres()
  {
    if (m_res != NULL)
      mysql_free_result(m_res);
  }

  operator MYSQL_RES* ()
  {
    return m_res;
  }

private:
  auto_mysqlres& operator= (const auto_mysqlres &res);
  auto_mysqlres (const auto_mysqlres &res);

private:
  MYSQL_RES *m_res;
};

when I try to use it this way auto_mysqlres result = return_pointer_to_mysql_res(); I get the error in GCC 4.6.3: auto_mysqlres::auto_mysqlres(const auto_mysqlres&) is private. no errors in MSVC 2008, though.

return_pointer_to_mysql_res returns MYSQL_RES*, of course I have fixed the problem with this line auto_mysqlres result (return_pointer_to_mysql_res());

but I want to find out why I get that error. I can't understand why GCC creates a temporary object there.

Was it helpful?

Solution

You are performing copy initialization here:

auto_mysqlres result = return_pointer_to_mysql_res();

This requires that a copy constructor be available, even if copies are elided. Semantically, you are constructing a temporary auto_mysqlres from a pointer on the RHS, and copy constructing from it on the LHS.

You can use direct initialization instead:

auto_mysqlres result(return_pointer_to_mysql_res());

see more on copy initialization and direct initializazion here.

As @Rapptz points out in a comment, in C++11, you could decide to make your class move copyable (and possibly move assignable), in which case the move copy constructor would be picked up in the copy initialization.

OTHER TIPS

Well.. @myself: Learning never stops. :)

Your constructor is not explicit and therefore a way to implicitly convert a MYSQL_RES* into as auto_mysqlres. This is what gcc does here. It converts the MYSQL_RES* into a auto_mysqlres and then tries to call the copy constructor. This is required here.

§ 8.5 [dcl.init] / 14

The initialization that occurs in the form

  • T x = a;

[...] is called copy-initialization.

You copy-inititalize your object.

§ 8.5 [dcl.init] / 16

[... If the initialization] is copy-initialization where the cv-unqualified version of the source type is the same class as, or a derived class of, the class of the destination, constructors are considered. [...]

Otherwise (i.e., for the remaining copy-initialization cases), user-defined conversion sequences that can convert from the source type to the destination type or (when a conversion function is used) to a derived class thereof are enumerated as described in 13.3.1.4, and the best one is chosen through overload resolution.

In your case MYSQL_RES* is not the same class as, or a derived class of the destination class (auto_mysqlres) so a conversion is required since the constructor isn't considered.

You'll either

  • have to do direct initialization

    auto_mysqlres result(return_pointer_to_mysql_res());

  • or provide a (move) copy constructor.

PS: Wasn't quite aware of where the cv-unqualified version of the source type is the same class as, or a derived class of, the class of the destination.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top