Thread: why aren't implicit type conversions transitive?

  1. #1
    Registered User
    Join Date
    May 2010
    Posts
    2

    Question why aren't implicit type conversions transitive?

    after a nice discussion with jdong on irc, we're wondering why..

    Code:
    struct Number {
      Number(const int &n) {
        num = n;
      }
      int num;
    };
      
    Number foo = 42;
      
    struct SpecialNumber {
      SpecialNumber(const Number &n) {
        num = n.num;
      }
      int num;
    };
      
    // this works fine
    SpecialNumber bla1 = Number(42);
    
    // won't compile
    SpecialNumber bla2 = 42;
    ..the second assignment at the end does not automatically cast to Number(42)?

    <jdong> bazkie: but the TRUE question is, what does C++ mean from an OOP standpoint when it lets you say "Number n = 42" ?
    as in, a
    Number bla(42);
    would seem logical: it's a number, initialized by some value.

    however, a
    Number bla = 42;
    seems ugly: bla IS NOT an integer itself, so why does C++ allow this?


    concluding, it's a 2-sided question:

    1. if C++ allows the Number bla = 42 way of calling a constructor, shouldn't it allow for a SpecialNumber bla = 42 as well?

    2. should not C++ disallow for both methods of calling a constructor for a more aesthetically sound OOP design?

  2. #2
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Only one implicit type conversion by construction is allowed. The reason why is that the standard says so.

    More practically, if multiple implicit constructor calls were allowed, there is a potential for ambiguity -- and even if there is no ambiguity, it could take the compiler a huge amount of effort to figure out which chain of conversions is the legal one.

    Imagine say, ten types, with various constructors that convert from one type to another. The compiler must determine, not only which constructors to use, but the order in which to use them, to ultimately transform type A into type Z. The big-O complexity of this is, I believe, O(N!)
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  3. #3
    Registered User
    Join Date
    May 2010
    Posts
    2
    heh, exactly what i thought (thanks for confirming), but yet the second question remains thanks for your reply btw.

    *edit: by the way:
    Only one implicit type conversion by construction is allowed. The reason why is that the standard says so.
    could you give me the paragraph/section number in ISO/IEC that proves that statement? we just like to see it to be sure
    Last edited by bazkie; 05-04-2010 at 06:17 PM.

  4. #4
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by bazkie View Post
    heh, exactly what i thought (thanks for confirming), but yet the second question remains thanks for your reply btw.
    I think the second question starts from the wrong basis. There is no difference from a semantic standpoint between

    Code:
    FooType a( bar );
    and

    Code:
    FooType a = bar;
    Both will result in a call to a constructor. The second version gets people in the beginning because it looks like an assignment. The reason this was allowed is because variable initializations in C look like this, and it was decided for reasons I'm not privy to, that the identical syntax should be allowed for initialization of objects (at least, when there is only one argument to the constructor).

    I'm guilty of using the second version much more often than the first. But I have no trouble remembering that it's a constructor call, not an assignment. Other people do (not to their detriment, it's a weird rule)


    *edit: by the way:

    could you give me the paragraph/section number in ISO/IEC that proves that statement? we just like to see it to be sure
    Probably a better question for LaserLight to answer, since I don't have the entire thing memorized like he does

    EDIT: In my previous example I said "ten types." In reality, the number of types is the total number of types in the entire program (at least what is visible from the current translation unit). The compiler must consider each possible chain of conversions, even if only just to produce an error that "this can't be done." A simple typo could result in a compile time of a thousand years.
    Last edited by brewbuck; 05-04-2010 at 06:33 PM.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  5. #5
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    2. If you don't like = mark your constructors explicit. Originally I'm sure that fell under "don't unnecessarily annoy C programmers" but even now int a(5) just seems wrong.

    Clause 12.3, paragraph 4, states
    Quote Originally Posted by ISO C++
    At most one user-defined conversion (constructor or conversion function) is implicitly applied to a single value.

  6. #6
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by tabstop View Post
    2. If you don't like = mark your constructors explicit. Originally I'm sure that fell under "don't unnecessarily annoy C programmers" but even now int a(5) just seems wrong.
    I think that even with explicit you can still use the assignment-looking syntax, but I'm too lazy to check. explicit prevents honest-to-God implicit conversions.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  7. #7
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Quote Originally Posted by brewbuck View Post
    I think that even with explicit you can still use the assignment-looking syntax, but I'm too lazy to check. explicit prevents honest-to-God implicit conversions.
    If I try it I get
    Code:
    interesting.cpp:11: error: conversion from ‘int’ to non-scalar type ‘Number’ requested
    with the code
    Code:
    struct Number {
          explicit Number(const int &n) {
                  num = n;
                    }
            int num;
    };
    
    
      int main() {
    // this works fine
    Number foo = 42;
    //
      }

  8. #8
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    That's because list initialization and assignment initialization are not the same.
    Code:
    Number n(5); // -> construct n using Number(int) constructor
    Number m = 5; // -> implicitly convert 5 to Number and initialize m with the resulting temporary
    in other words, the second statement is interpreted as
    Code:
    Number m = Number(5);
    but only after validation, of course; i.e. an explicit constructor is not allowed. Besides, the implicit conversion could also use a conversion operator, i.e.
    Code:
    Number m = someSpecialNumber;
    could be interpreted as
    Code:
    Number m = someSpecialNumber.operator Number();
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. how do you resolve this error?
    By -EquinoX- in forum C Programming
    Replies: 32
    Last Post: 11-05-2008, 04:35 PM
  2. Script errors - bool unrecognized and struct issues
    By ulillillia in forum Windows Programming
    Replies: 10
    Last Post: 12-18-2006, 04:44 AM
  3. Help! About Type Conversions
    By Antigloss in forum C Programming
    Replies: 1
    Last Post: 05-28-2006, 09:24 PM
  4. Dynamic array of pointers
    By csisz3r in forum C Programming
    Replies: 8
    Last Post: 09-25-2005, 02:06 PM
  5. Problem with Visual C++ Object-Oriented Programming Book.
    By GameGenie in forum C++ Programming
    Replies: 9
    Last Post: 08-29-2005, 11:21 PM

Tags for this Thread