Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

C++ has a feature (I cannot figure out the proper name of it), that automaticall

ID: 654311 • Letter: C

Question

C++ has a feature (I cannot figure out the proper name of it), that automatically calls matching constructors of parameter types if the argument types are not the expected ones.

A very basic example of this is calling a function that expects a std::string with a const char* argument. The compiler will automatically generate code to invoke the appropriate std::string constructor.

I'm wondering, is it as bad for readability as I think it is?

Here's an example:

class Texture {
public:
    Texture(const std::string& imageFile);
};

class Renderer {
public:
    void Draw(const Texture& texture);
};

Renderer renderer;
std::string path = "foo.png";
renderer.Draw(path);
Is that just fine? Or does it go too far? If I shouldn't do it, can I somehow make Clang or GCC warn about it?

Explanation / Answer

This is referred to as a converting constructor (or sometimes implicit constructor or implicit conversion).

I'm not aware of a compile-time switch to warn when this occurs, but it's very easy to prevent; just use the explicit keyword.

class Texture {
public:
explicit Texture(const std::string& imageFile);
};
As to whether or not converting constructors are a good idea: It depends.

Circumstances in which implicit conversion makes sense:

The class is cheap enough to construct that you don't care if it's implicitly constructed.
Some classes are conceptually similar to their arguments (such as std::string reflecting the same concept as the const char * it can implicitly convert from), so implicit conversion makes sense.
Some classes become a lot more unpleasant to use if implicit conversion is disabled. (Think of having to explicitly invoke std::string every time you want to pass a string literal. Parts of Boost are similar.)
Circumstances in which implicit conversion makes less sense:

Construction is expensive (such as your Texture example, which requires loading and parsing a graphic file).
Classes are conceptually very dissimilar to their arguments. Consider, for example, an array-like container that takes its size as an argument:
class FlagList
{
FlagList(int initial_size);
};

void SetFlags(const FlagList& flag_list);

int main() {
// Now this compiles, even though it's not at all obvious
// what it's doing.
SetFlags(42);
}
Construction may have unwanted side effects. For example, an AnsiString class should not implicitly construct from a UnicodeString, since the Unicode-to-ANSI conversion may lose information.

Hire Me For All Your Tutoring Needs
Integrity-first tutoring: clear explanations, guidance, and feedback.
Drop an Email at
drjack9650@gmail.com
Chat Now And Get Quote