2

I modified the question here. Now it looks muck like a answer, :). Thank you all for sort this out.

I have some overloaded constructor in my class, Like this

#include <string>

#ifdef EXPLICIT_ENUM_CONVERSION
enum struct E
#else
enum E
#endif
{
    A,
    B
};

class A
{
public:
  A(unsigned int i){};
  A(std::string const& s){};
};

And a function declaration that actually accept A as a parameter

void func(const class A& a)
{
}

But the caller is invoking it by passing a enum.

int main()    
{
#ifdef EXPLICIT_ENUM_CONVERSION
  E e=E::A;
  func((unsigned int)e);  
#else
  E e=A;
  func(e);  
#endif
}

Question: By commenting out the A(unsigned) and compile again to get an error, I can tell that the constructor that is used. But is there a better way to tell how the types are converted from the gcc command line or objdump the result?

Answer: If compiling with -O0 and then use objdump -CSr, the class constructor used is shown from the objdump.

Question: is there any way to prevent the enum to unsigned automatic conversion with gcc?

Answer: See the answer I picked. The scoped enum is introduced in C++11 and can satisfy the purpose. You can check the code within EXPLICIT_ENUM_CONVERSION.

Zhang Li
  • 117
  • 1
  • 11
  • 1
    `void main` isn't valid C++ program – Danh Jan 06 '17 at 10:22
  • 2
    _is there any way to prevent the enum to u32 automatic conversion with gcc_ Use Scoped enumerations – Danh Jan 06 '17 at 10:24
  • 1
    Use scoped enumerations *by default*. – DeiDei Jan 06 '17 at 10:25
  • *"is there a better way to tell how the types are converted from the gcc"* - Learn the (conversion) rules from the standard, you do not have to look at generated code to know which version of the constructor is called, this is well defined by the standard. – Holt Jan 06 '17 at 10:26
  • It is theoretically possible for an IDE to show which of the overloads is being used in a call, but I don't know if any of them do. Other than that, no, there's no easy way to see that. – n. m. could be an AI Jan 06 '17 at 10:26
  • Make your single argument constructors explicit. See also: http://stackoverflow.com/questions/121162/what-does-the-explicit-keyword-in-c-mean – Richard Critten Jan 06 '17 at 10:34
  • @OP Also be aware of the issue of (over)using conversion operators, where conversions are going on at runtime without being aware of them. It isn't just constructors that have this issue. – PaulMcKenzie Jan 06 '17 at 11:21
  • 1
    `A` has private constructors, neither of those would work. And even if it didn't, `func(e)` still does not work because `A&` cannot bind to the temporary conversion result. This code is a long way from anything resembling working code. It would be better if you post a [MCVE](http://stackoverflow.com/help/mcve) – M.M Jan 06 '17 at 11:41
  • When you have actually got the code working, look at the intermediate assembly output, it will show the name of the function being called – M.M Jan 06 '17 at 11:44

1 Answers1

2

Here are 3 suggestions depending on your goal:

If you want to understand conversion rules better:

  1. read the relevant parts in the book Accelerated C++ (preference, steps in conversion)
  2. read the relevant parts in the book More Effective C++ (no more than 1 implicit conversion)
  3. read the C++ standard, e.g. the C++14 draft

If you want to find some bug:

  • use printf-debugging or logging in your ctors
  • or use a debugger
  • or break down your code into smaller steps, e.g.

    E e;       
    auto i = static_cast<u32>(e);
    func(i);
    

    static_cast<u32>(e) uses explicitly typed initializer idiom (see Effective Modern C++ Item 6)

If you want to avoid bugs, you should avoid too complex implicit conversions and be wary of user-defined conversion functions (More Effective C++ Item 5). For instance:

  • explicit conversion ctor: explicit A(u32 i){};
  • scoped enum: enum class E{...}
  • scoped enum as ctor parameter: A(E enumElement){};
Jarod42
  • 203,559
  • 14
  • 181
  • 302
DaveFar
  • 7,078
  • 4
  • 50
  • 90
  • 1
    The concept scoped enum seems introduced by C++11. **scoped_enum.cc:1:1: warning: scoped enums only available with -std=c++11 or -std=gnu++11** . The new concept is really useful and prevent the default conversion to int. – Zhang Li Jan 07 '17 at 02:20