Question

I'm having a bizarre error, where the compile accepts the code, but does an implicit construction of a type. Previously this wouldn't compile until I added a constructor for the Value class. Here is an example of how my code is set up, but this fails to compile as expected.

#include <iostream>
#include <cassert>


enum class Type {
    Null = 0
    ,Char
    ,Int32
    //etc
};


// My variant class.
class Value {
public:
// I also have templated constructors for Value...
    Value( Type type, void* data = nullptr ) {
        //construct type from data.
        assert( false );
    }
    friend std::ostream& operator<<( std::ostream& os, const Value& v);
};

// If the insertion operator is defined globally, not within the class, then the compiler
// will do the implicit conversion.
std::ostream& operator<<( std::ostream& os, const Value& v) {
    return os << "Printing Value";
}

// In my code, what this really does is get the type from the lua stack
// and converts the type to my own. I'll just do a c style cast here.
Type getType( int i ) { return (Type)i; }


int main() {
    // In my code, this statement compiles, but implicitly constructs Value 
    // from the return type "Type".
    std::cout << getType( 2 ) << "\n";
    return 0;
}

Has anyone ran into this problem before? Are there any language features that would cause this to take place? What types of things should I look for to prevent this from happening?(I know I can just change the constructor to require the "data" parameter, but I'm looking for the root cause)

Edit: I figured out what allows the compiler to do the implicit conversion, see below.

Was it helpful?

Solution

Your class has a conversion constructor that converts an object of type Type to an object of type Value

Value( Type type, void* data = nullptr ) {
    //construct type from data.
    assert( false );
}

So then you write

std::cout << getType( 2 ) << "\n";

operator << is not overloaded for type Type. So the compiler tries to convert implicitly the operand of the operator to type that can be used with the operator. And it finds such conversion because you have the conversion constructor.

You should declare the constructor as

explicit Value( Type type, void* data = nullptr );
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top