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.
Related Questions
drjack9650@gmail.com
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.