1

I am trying to support implicit casts of literal values in a type system. These implicit casts are intended and ideal (See note 1). I'm aware that C++ can perform multiple implicit casts in an expression. The second line of main below does not work.

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

class B {
public:
    B(const A&);
};

int main(void)
{
    A("example");  // this works
    B("example");  // this does not work
}

If I add a const char* constructor to A, the second line works...

class A {
public:
    A(const char*);
    A(const std::string&);
};

class B {
public:
    B(const A&);
};

int main(void)
{
    A("example");  // this works
    B("example");  // now it works
}

Why does the first implementation not work? The second line could construct the const char* into a std::string, then into a A, and finally B.

Note 1: The values of the types that are implicitly castable are the same values, the type only represents that the value has passed a pre-condition, holds it's condition through operations, and propogates that condition through operations on similar types. The implicit casting is allowed for types to other types with weaker pre-conditions.

songyuanyao
  • 169,198
  • 16
  • 310
  • 405
ktb
  • 1,498
  • 10
  • 27
  • 1
    Possible duplicate of [Multiple implicit conversions on custom types not allowed?](https://stackoverflow.com/questions/12847272/multiple-implicit-conversions-on-custom-types-not-allowed) – François Andrieux Oct 04 '19 at 15:12
  • There is no such thing as an implicit cast. The question is about implicit **conversions**. A cast is something you write in your source code to tell the compiler to do a conversion. – Pete Becker Oct 04 '19 at 20:41

2 Answers2

4

Unlike standard conversions, implicit conversion sequence can consist of one user-defined conversion at most.

Implicit conversion sequence consists of the following, in this order:

1) zero or one standard conversion sequence;

2) zero or one user-defined conversion;

3) zero or one standard conversion sequence.

For your 1st code snippet, given B("example");, two user-defined conversions are required; const char* to std::string and std::string to A.

As the workaround, you can add another conversion constructor as you tried, or add explicit conversion to construct B, e.g.

B(A("example"));
songyuanyao
  • 169,198
  • 16
  • 310
  • 405
  • Well that sucks. Is the only way around this to add implicit casts for every type in my system to every other type? I was hoping to make my library incremental, only include what you use, this would inhibit that. Every type would need every other type's definition, so you could only include the whole thing. – ktb Oct 04 '19 at 15:21
-2

To realize an implicit cast you must put the data type between parentheses, followed by the variable(int)(var)

  • 3
    That's an **explicit** type conversion. It's the opposite of an implicit conversion. Using C style casts (like `(int)`) is also discouraged in C++. It's preferable to use weaker and safer cast expressions like `static_cast`. – François Andrieux Oct 04 '19 at 15:16
  • To reviewers: if the answer is wrong but is an answer (like this is), don't recommend deletion: downvote! See, for example, "[You're doing it wrong: A plea for sanity in the Low Quality Posts queue](http://meta.stackoverflow.com/q/287563/1364007)" and "[When an answer answers the wrong question, is it Not An Answer?](https://meta.stackexchange.com/a/185162/284827)". This is an answer. You may not agree with it, but it is an attempt to answer the question. [From Review](https://stackoverflow.com/review/low-quality-posts/24225612) – Wai Ha Lee Oct 05 '19 at 03:07