"Ambiguity between" error

I'm "porting" this code from BCB6 to BCB2010, and am getting the following error:

#include <stdarg.h>
#include <vector>
#ifdef __BORLANDC__
#include "dxmdaset.hpp"
#pragma package(smart_init)
#endif
...
void myclass::VariantToSQL(Variant &v, String &dest)
{
    ....
    TDateTime datetime;
    ....
    switch (v.Type())
    {
        case varDate:
            datetime = (System::TDateTime)(v.AsType(varDate));   // Line 1830

            // was:
            // datetime = (TDateTime)v;

            // These variations also don't work:
            // datetime = v.AsType(varDate));
            // datetime = (TDateTime)(v.AsType(varDate));
            // datetime = (System::TDateTime)(v.AsType(varDouble));
    ...
}

[BCC32 Error] myclass.cpp(1830): E2015 Ambiguity between '_fastcall System::TDateTime::TDateTime(const System::TDateTime &) at c:\program files\embarcadero\rad studio\7.0\include\vcl\systdate.h:44' and '_fastcall System::TDateTime::TDateTime(const double) at c:\program files\embarcadero\rad studio\7.0\include\vcl\systdate.h:45'

Unlike the other posts I found regarding this sort of problem, I can't change the class to de-ambiguify the call.  I'm a little mystified why the compiler can't tell that I'm passing it a TDateTime type.

I know just enough C++ to get by, and I didn't write this code.  I bet one of you guys can spot the stupidity.  Thanks so much for your help!
kmustang1Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

CarnouCommented:
This makes sense to me only if System::TDateTime is a double or double &.  If that's the case, you could possibly resolve the error by commenting out line 44 or line 45 of c:\program files\embarcadero\rad studio\7.0\include\vcl\systdate.h .  Normally, you don't want to screw with library code, but in this case, it's probably ok to.  I expect you could get rid of either line.  I think I would choose 44 - you don't need the parameter to be a reference; it's being used as a copy constructor.
Comment out the line, and see if everything still compiles and works.  *:-]
Good luck!
0
kmustang1Author Commented:
I'm not a big fan of changing (for lack of a better term) my compiler, but just for grins, I tried commenting out line 44.  This generates the error:

[BCC32 Error] cpnetclasses.cpp(1830): E2015 Ambiguity between 'System::TDateTime::TDateTime(const System::TDateTime &) at c:\program files\embarcadero\rad studio\7.0\include\vcl\systdate.h:129' and '_fastcall System::TDateTime::TDateTime(const double) at c:\program files\embarcadero\rad studio\7.0\include\vcl\systdate.h:45'

Line 129?  Really?  Here is line 129 (and 130):
    void __fastcall DecodeTime(unsigned short* hour, unsigned short*
           min, unsigned short* sec, unsigned short* msec) const;

That REALLY makes no sense.  Bogus compiler message maybe?
0
CarnouCommented:
I'll have to state some seemingly obvious things:
The message would imply that line 129 uses a reference to TDateTime.  
Obviously, the line you copy-pasted does not.  
Either the message is totally from left field, or maybe somehow the line you pulled isn't line 129?  Sorry, I know that's almost offensive in its implication, but it frequently makes more sense for a human to go to the wrong line than for the compiler to make up random numbers.
Unless you made a mistake with your line number, I have no idea why the compiler is telling you that.
Two things to try:
  • Uncomment line 44 and comment line 45, and see what that does for you.
  • Search everywhere within c:\program files\embarcadero\rad studio\7.0\include for TDateTime, preferably with a #define in the same line.  I would like to know that TDateTime really is defined as.  The searching itself won't fix anything, but it might give us a better idea as to what this message is really about.
0
Cloud Class® Course: Microsoft Windows 7 Basic

This introductory course to Windows 7 environment will teach you about working with the Windows operating system. You will learn about basic functions including start menu; the desktop; managing files, folders, and libraries.

kmustang1Author Commented:
I know, Carnou.  It makes no sense.  I quadruple checked the line number, and looked at the surrounding lines...  

I got pulled off to something else this afternoon, I'll have to do the searching you suggest in the morning.  I also wondered as I was typing that if TDateTime was defined in multiple places.  I didn't invest a lot in that line of thinking because the list of includes in both the .h and .cpp files was so short.  It's worth checking, though.

Thanks!  I'll report back as soon as I get this "easy" (heh) addition to something else done.
0
kmustang1Author Commented:
Alrighty, here's the update...

I searched for TDateTime in the include directory, and didn't find any other declarations.  It's used many places, but there are no #defines or other definitions.  There were 164 matches, I can attach them if you'd like, but without the contexts around the matches, I didn't think it would be all that useful to you.

I switched which line was commented out, and got a less insane error message, so I stuck with that and did a little more experimentation. I can get the error to change ever so slightly.  Is there a clue here?

      datetime = (TDateTime)(v.AsType(varDate));
      datetime = (TDateTime)(v.AsType(VT_DATE));  // I found this value in the search results and tried it
both generate:
     [BCC32 Error] myclass.cpp(1830): E2015 Ambiguity between '_fastcall System::TDateTime::TDateTime(const System::TDateTime &) at $(BCB)\include\vcl\systdate.h:44' and '_fastcall System::TDateTime::TDateTime(const int) at $(BCB)\include\vcl\systdate.h:46'

      datetime = v.AsType(varDate);
      datetime = v.AsType(VT_DATE);
both generate:
     [BCC32 Error] myclasse.cpp(1830): E2015 Ambiguity between '_fastcall operator System::TDateTime::=(const System::TDateTimeBase &) at $(BCB)\vcl\systdate.h:56' and '_fastcall operator System::TDateTime::=(const System::TDateTime &) at $(BCB)\include\vcl\systdate.h:58'

I've attached the complete contents of systdate.h, including my one little edit.
// SYSTDATE.H: Pascal TDateTime support
// Copyright (c) 1997, 2002 Borland Software Corporation

#if !defined(SYSTDATE_H)
#define SYSTDATE_H

#if !defined(SystemHPP)
#error Do not include this file directly.  Include 'System.hpp'.
#endif

#if !defined(SYSMAC_H)
#include <sysmac.h>
#endif
#if !defined(DSTRING_H)
#include <dstring.h>
#endif
#if !defined(WSTRING_H)
#include <wstring.h>
#endif

#pragma option push -w-inl -w-lvc

namespace System
{
  class RTL_DELPHIRETURN TDateTimeBase
  {
  public:
    double Val;
  };

  class RTL_DELPHIRETURN TDateTime : public TDateTimeBase
  {
  public:
    // Used by TDateTime(const System::String& src)
    enum TDateTimeFlag {Date, Time, DateTime};

    static TDateTime __fastcall CurrentDate();
    static TDateTime __fastcall CurrentTime();
    static TDateTime __fastcall CurrentDateTime();
    static TDateTime __fastcall FileDateToDateTime(int fileDate);

    __fastcall TDateTime()                                  {Val = 0;}
    __fastcall TDateTime(const TDateTimeBase& src)          {Val = src.Val;}
    __fastcall TDateTime(const TDateTime& src)              {Val = src.Val;}
//    __fastcall TDateTime(const double src)                  {Val = src;}
    __fastcall TDateTime(const int src)                     {Val = src;}
    __fastcall TDateTime(const System::String& src, TDateTimeFlag flag = DateTime);
    __fastcall TDateTime(unsigned short year, unsigned short month,
            unsigned short day);
    __fastcall TDateTime(unsigned short hour, unsigned short min,
            unsigned short sec, unsigned short msec);
    __fastcall TDateTime(unsigned short year, unsigned short month,
            unsigned short day, unsigned short hour, unsigned short min,
            unsigned short sec, unsigned short msec);

    TDateTime& __fastcall operator =(const TDateTimeBase& rhs)
    {Val = rhs.Val;return *this;}
    TDateTime& __fastcall operator =(const TDateTime& rhs)
    {Val = rhs.Val;  return *this;}
    TDateTime& __fastcall operator =(const double rhs)
    {Val = rhs; return *this;}
    TDateTime& __fastcall operator =(const int rhs)
    {Val = rhs; return *this;}

    TDateTime& __fastcall operator +=(const TDateTimeBase& rhs)
    {Val+=rhs.Val;return *this;}
    TDateTime& __fastcall operator +=(const TDateTime& rhs)
    {Val += rhs.Val; return *this;}
    TDateTime& __fastcall operator +=(const double rhs)
    {Val += rhs; return *this;}
    TDateTime& __fastcall operator +=(const int rhs)
    {Val += rhs; return *this;}

    TDateTime& __fastcall operator -=(const TDateTimeBase& rhs)
    {Val-=rhs.Val;return *this;}
    TDateTime& __fastcall operator -=(const TDateTime& rhs)
    {Val -= rhs.Val; return *this;}
    TDateTime& __fastcall operator -=(const double rhs)
    {Val -= rhs; return *this;}
    TDateTime& __fastcall operator -=(const int rhs)
    {Val -= rhs; return *this;}

    TDateTime& operator ++() {Val++; return *this;}
    TDateTime operator ++(int) {TDateTime tmp(*this); Val++; return tmp;}
    TDateTime& operator --() {Val--; return *this;}
    TDateTime operator --(int) {TDateTime tmp(*this); Val--; return tmp;}

    TDateTime __fastcall operator +(const TDateTimeBase& rhs) const
    {return Val+rhs.Val;}
    TDateTime __fastcall operator +(const TDateTime& rhs) const
    {return Val+rhs.Val;}
    TDateTime __fastcall operator +(const double rhs) const {return Val+rhs;}
    TDateTime __fastcall operator +(const int rhs) const {return Val+rhs;}

    TDateTime __fastcall operator -(const TDateTimeBase& rhs) const
    {return Val-rhs.Val;}
    TDateTime __fastcall operator -(const TDateTime& rhs) const
    {return Val-rhs.Val;}
    TDateTime __fastcall operator -(const double rhs) const {return Val-rhs;}
    TDateTime __fastcall operator -(const int rhs) const {return Val-rhs;}

    // comparisons
    bool __fastcall operator ==(const TDateTime& rhs) const
    {return Val == rhs.Val;}
    bool __fastcall operator !=(const TDateTime& rhs) const
    {return Val != rhs.Val;}
    bool __fastcall operator >(const TDateTime& rhs) const
    {return Val > rhs.Val;}
    bool __fastcall operator <(const TDateTime& rhs) const
    {return Val < rhs.Val;}
    bool __fastcall operator >=(const TDateTime& rhs) const
    {return Val >= rhs.Val;}
    bool __fastcall operator <=(const TDateTime& rhs) const
    {return Val <= rhs.Val;}

   
    __fastcall operator System::String() const;//<Date||Time||DateTime>String(smart)
    System::String __fastcall FormatString(const System::String& format) const;
    System::String __fastcall DateString() const;
    System::String __fastcall TimeString() const;
    System::String __fastcall DateTimeString() const;
    __fastcall operator double() const {return Val;}
    __fastcall operator int() const    {return (int)Val;}

    int __fastcall DayOfWeek() const;
    int __fastcall FileDate() const;
    void __fastcall DecodeDate(unsigned short* year, unsigned short*
           month, unsigned short* day) const;
    void __fastcall DecodeTime(unsigned short* hour, unsigned short*
           min, unsigned short* sec, unsigned short* msec) const;
  };

  // NOTE: Insertion/Extraction operators of VCL classes are only visible
  //       if VCL_IOSTREAM is defined.
  //
  #if defined(VCL_IOSTREAM)
  std::ostream& operator <<(std::ostream& os, const TDateTime& arg);
  std::istream& operator >>(std::istream& is, TDateTime& arg);
  #endif

}

#pragma option pop

#endif

Open in new window

0
CarnouCommented:
Hi kmustang1,
Thanks for the thorough debugging information.  By posting systdate.h, I got a much better idea of what's going on.
As far as I can tell, you found VT_DATE as a #define of varDate.  If so, the two types are exactly the same thing.
First of all, the only member inside TDateTimeBase is a double, and TDateTime doesn't include any members at all, which is why the compiler is confusing both of them as doubles, and explains the errors the compiler was giving that you posted in your first two postings.  In both cases, your code is typecasting v to be a TDateTime, and the typecast is invoking the copy constructor, and it doesn't know which constructor to use.
The final error you got was when you stopped typecasting, and so your right-hand-side was ok, but then the compiler got confused by the =.  The right hand side is a TDateTime, but because of inheritance, it is also a TDateTimeBase, and the compiler didn't know which to choose.
Now, I know you didn't code systdate.h, so let me say - that's some pretty ugly coding!  I'm more willing to play with library level code than you.  I would rewrite the whole thing.  I'd put all the operators that deal with TDateTimeBase inside TDateTimeBase, and that would probably solve everything else.  If that didn't work, I would just comment out all the functions that operates on the TDateTimeBase.  
You could also probably resolve all of this confusion simply by adding some unnecessary members to TDateTimeBase and TDateTime.  Under the line double Val; in TDateTimeBase, add an extra member, such as char foo;  In TDateTime, under the enum line, add an extra member, such as int bar;  By doing this, you should resolve the compiler's confusion as to whether an object is a double, a TDateTimeBase, or a TDateTime.
I don't know your compiler well enough.  There may be a #pragma you can use that will tell it to stop being stupid.  Something that tells it to resolve conflicts by using the most derivable class.
But... I'm guessing you don't like any of those answers.  Let me instead give you some alternatives that let you get the .h to exactly the way it was, and you can try to code around the poorly coded library header.
So here's what I see.  You were trying to typecast to make it easier for the compiler and resolve the ambiguity as to whether it's a TDateTime or TDateTimeBase, but in doing so, you got the compiler even more confused, because it started trying to figure out what copy constructor to use.  By removing the typecast and simply having datetime = v.asType(varDate), you went back to only confusing the compiler about one thing.  Your best bet is to try any of the different kinds of typecasting.  Hopefully, one of them will work to unconfuse the compiler.
Instead of saying datetime = (TDateTime)v.asType(varDate), try using any of the following kinds of typecasts.  Maybe one of them will make your compiler happy:
  • datetime = TDateTime(v.asType(varDate));
  • datetime = static_cast<TDateTime>(v.asType(varDate));
  • datetime = dynamic_cast<TDateTime>(v.asType(varDate));
With luck, any of these may work.
We've gotten a bit closer.  Let me know how it goes!
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
CarnouCommented:
PS: the reference I used on type casting is here: http://www.cplusplus.com/doc/tutorial/typecasting/
0
George TokasCommented:
This is a common error using C++ Builder...
My own experience with this issue is when trying to use IntToStr()...
Try
datetime = VarToDateTime(&v);
This works for me here with BCB2010..

George Tokas.
0
kmustang1Author Commented:
You guys are going to love this...

Here's a little bit more code context:

    TDateTime datetime;
    double temp;
    switch (v.Type())
    {
    case varDate
         // datetime = (TDateTime)(v.AsType(VT_DATE));
         // temp = datetime;
         temp = v.AsType(VT_DATE);
         if (temp == 0.0)
         {
            dest += "";
         }
    }

Remember I didn't write this code and have pretty much solely been focusing on fixing the Ansi String to Unicode String issues.  After my last post, I noticed that it wasn't REALLY assigning the value to datetime, but was using that for a two step conversion to temp, which is a double.  Take out the intermediate step, and it works.  Huh.

Thank you, George, for your comment.  I will hit hit the Issue with IntToString() in the next round.  I am saddened to see that Embarcadero has graduated from the Microsoft school of documentation, so now I can't find ANYthing.  I tried to find VarTo* functionality, but was not successful.  The functions are not part of the class so are not in the documentation for Variant, nor visible when you Find Declaration.  *sigh*

And Carnou, your post is VERY helpful, I think I understand the problem better now.

After I get through this first gauntlet and get my test program up and running, I hope to go through and fix some of these bad coding practice issues.  I'm already having to take a much bigger step than I would like, and am trying to do as little as possible in this pass, because that's already some pretty big change to code that I don't fully understand (yet).

Thank you both!
0
George TokasCommented:
>>Thank you, George, for your comment.  I will hit hit the Issue with IntToString() in the next round.  I am saddened to see that Embarcadero has graduated from the Microsoft school of documentation, so now I can't find ANYthing.  I tried to find VarTo* functionality, but was not successful.  The functions are not part of the class so are not in the documentation for Variant, nor visible when you Find Declaration.  *sigh*


The documentation for VarToDateTime comes from BCB6 I'm working with on THIS machine.
I tried the functionality of VarToDateTime on a machine NEXT to this where using Win7 64bit and RAD Studio 2010...
It worked so I posted the "solution".
I have the same issues with you regarding help documentation BUT I didn't install help files with RAD Studio...
Earlier versions (2009) didn't had any problem for as far as I worked with them.
I'm using BCB6 here JUST BECAUSE there are some libraries I can't port to 2010...

George Tokas.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Editors IDEs

From novice to tech pro — start learning today.