[C++] ambiguous call to overloaded function probleem

Pagina: 1
Acties:
  • 125 views sinds 30-01-2008
  • Reageer

  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Ik heb een probleem met de volgende code. De twee statements in main zou ik liefst zo willen houden, maar zonder de dubbelzinnigheid natuurlijk.
Een oplossing zou zijn het toevoegen van open(const char*), maar is er geen oplossing zonder extra functies?
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include "stdafx.h"
#include <string>
#include <windows.h>

using namespace std;

class Cwin_handle  
{
public:
    Cwin_handle(HANDLE h);
};

class Ccc_file  
{
public:
    int open(const Cwin_handle& h);
    int open(const string& name);
};

int main()
{
    Cwin_handle h = CreateFile(0, 0, 0, 0, 0, 0, 0);
    Ccc_file().open("");
    return 0;
}

jwt.cpp(23) : error C2668: 'open' : ambiguous call to overloaded function

[ Voor 10% gewijzigd door Olaf van der Spek op 15-03-2003 19:41 ]


Verwijderd

ik weet niet hoe dit bij C++ zit, maar in Delphi kun je dit oplossen door je haakjes specifiek te casten naar een string, zodat er geen onduidelijkheid meer is.. dus:

C++:
1
ccc_file().open(string(""));

  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Verwijderd schreef op 15 maart 2003 @ 19:45:
ik weet niet hoe dit bij C++ zit, maar in Delphi kun je dit oplossen door je haakjes specifiek te casten naar een string, zodat er geen onduidelijkheid meer is.. dus:

C++:
1
ccc_file().open(string(""));
Ja, dat kan (en werkt), maar ik wil eigenlijk een oplossing zonder aanpassing van die statements.

Verwijderd

eh? Je wilt enerzijds geen extra functies maken, maar wilt ook geen statements aanpassen.

hmm.. ik vraag me af hoe je het dan voor ogen had gehad? Je zult toch echt iets moeten veranderen wil het werken ?

//edit

nog een poging dan.. wat je ook zou kunnen doen is niet overloaden, maar gebruik maken van een eigen routine om te bepalen wat voor type iets is.

dus (pseudo code):

code:
1
2
3
4
5
6
functie mijnfunctie (input: ongetypeerd ) //bv variant in delphi
  begin
     als input van type string dan doedit, anders
     als input van type handle dan doedit, anders,
     enz.
  end

[/code]

[ Voor 50% gewijzigd door Verwijderd op 15-03-2003 20:19 ]


  • madwizard
  • Registratie: Juli 2002
  • Laatst online: 26-10-2024

madwizard

Missionary to the word of ska

Zoals hezik al zei zal je toch wat aan moeten passen. Aangezien een HANDLE eigenlijk een void * is zijn er voor char * 2 conversies mogelijk en de een heeft geen hogere prioriteit ofzo dus de call is ambigu.
Je zou de Cwin_handle(HANDLE h) constructor explicit kunnnen maken maar dan moet je je eerste statement toch aanpassen (CreateFile return waarde als parameter ipv rechterkant van een assignment).
Volgens mij is de makkelijkste oplossing nog gewoon de open(HANDLE) een andere naam te geven, bijvoorbeeld attach(HANDLE) (eigenlijk opent de functie het bestand ook niet, want dat is al gedaan).

www.madwizard.org


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-08 13:19

.oisyn

Moderator Devschuur®

Demotivational Speaker

madwizard: ik weet niet welke compiler er gebruikt wordt, maar "" is volgens de C++ standaard een const char [1], en kan dus niet impliciet gecast worden naar een void * (die dus niet const is)

maw, die error zou er helemaal niet moeten zijn. Welke compiler gebruik je, OlafvdSpek?


.edit: hmm die error treedt zo te zien ook op in VC++ .net 2003 RC3. Ik heb 'm als bug gesubmit bij microsoft, en in de vs.net beta nieuwsgroep gepost. 'Ns kijken wat de MS mensen erover te zeggen hebben :)

[ Voor 47% gewijzigd door .oisyn op 15-03-2003 21:12 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • madwizard
  • Registratie: Juli 2002
  • Laatst online: 26-10-2024

madwizard

Missionary to the word of ska

Je hebt gelijk, is inderdaad een bug dan. Dit compileert ook gewoon vrolijk :):
C++:
1
2
3
void *pv = "blah";
char *pc = static_cast<char*>(pv);
*pc = 'a'; // access violation

www.madwizard.org


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-08 13:19

.oisyn

Moderator Devschuur®

Demotivational Speaker

toch raar, want dit compileert weer wel gewoon zonder errors over een ambiguous call (vc++ 7.1 rc3 dus)

C++:
1
2
3
4
5
6
7
void func (void *);
void func (const char *);

void bla ()
{
    func ("test");
}


:)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • madwizard
  • Registratie: Juli 2002
  • Laatst online: 26-10-2024

madwizard

Missionary to the word of ska

Ja maar daar is er voor de ene func een conversie nodig en voor de ander niet. Volgens mij heeft het laatste prioriteit.

www.madwizard.org


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-08 13:19

.oisyn

Moderator Devschuur®

Demotivational Speaker

oh ja da's natuurlijk ook weer zo... bij die 2 classes is er idd altijd wel een conversion. Maar als je van die const char * een const void * maakt weet ie er hier ook wel raad mee

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

beetje dirty, maar kun je voor dat stukje niet iets doen met compiler directives?

mits voorzien van commentaar zou dat geen probleem moeten zijn, toch?

[ Voor 14% gewijzigd door Verwijderd op 15-03-2003 22:24 ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-08 13:19

.oisyn

Moderator Devschuur®

Demotivational Speaker

en wat voor directive had je dan in gedachten :?

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

Dat zou ik zo niet kunnen zeggen, heb geen C++ hier, nog even afgezien van het feit dat TS nog niet heeft aangegeven welke compiler hij gebruikt.

Gezien deze opmerking:
madwizard: ik weet niet welke compiler er gebruikt wordt, maar "" is volgens de C++ standaard een const char [1],
lijkt me dat het probleem niet in de code zit, maar in de routine vd. compiler welke controleerd of een aanroep correct is. Soms zijn dat soort controles uit te zetten.

Kan best dat dat in dit geval niet zo is overigens, maar het kan geen kwaad even te kijken ..

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-08 13:19

.oisyn

Moderator Devschuur®

Demotivational Speaker

Mja, als ik OlafvdSpek's post history een beetje ken gebruikt hij gewoon VC++, en dan is het niet uit te zetten (misschien wel door alle extensions uit te zetten, maar dan compilet de helft van de headers niet meer, dus dat is niet aan te raden)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 13-08 16:46

curry684

left part of the evil twins

madwizard schreef op 15 maart 2003 @ 21:46:
Je hebt gelijk, is inderdaad een bug dan. Dit compileert ook gewoon vrolijk :):
C++:
1
2
3
void *pv = "blah";
char *pc = static_cast<char*>(pv);
*pc = 'a'; // access violation
Deze compileert hiero ook perfect onder VC.net:
C++:
1
strcpy("fiets", "bier");

Redelijk ernstige bug.... :X

Voor Olaf: enige mogelijke workaround hier is om een extra overload voor die functie te maken die een const char* neemt, omdat dat een conversieroute korter is (0 namelijk) dan de andere 2.

[edit]
Originele code van Olaf geeft overigens de volgende toelichting in VC.net:
code:
1
2
3
4
PalTst_Main.cpp(43) : error C2668: 'Ccc_file::open' : ambiguous call to overloaded function
        PalTst_Main.cpp(34): could be 'int Ccc_file::open(const std::string &)'
        PalTst_Main.cpp(33): or       'int Ccc_file::open(const Cwin_handle &)'
        while trying to match the argument list '(char [1])'

Je kunt dus zien dat ie het volkomen fout parset... ;(

[ Voor 39% gewijzigd door curry684 op 15-03-2003 22:56 . Reden: Blah geen bold in code block ]

Professionele website nodig?


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-08 13:19

.oisyn

Moderator Devschuur®

Demotivational Speaker

curry684 schreef op 15 March 2003 @ 22:42:
[edit]
Originele code van Olaf geeft overigens de volgende toelichting in VC.net:
code:
1
2
3
4
PalTst_Main.cpp(43) : error C2668: 'Ccc_file::open' : ambiguous call to overloaded function
        PalTst_Main.cpp(34): could be 'int Ccc_file::open(const std::string &)'
        PalTst_Main.cpp(33): or       'int Ccc_file::open(const Cwin_handle &)'
        while trying to match the argument list '[b](char [1])[/b]'

Je kunt dus zien dat ie het volkomen fout parset... ;(


bij mij geeft ie het type wel goed:

code:
1
2
3
4
error C2668: 'Ccc_file::open' : ambiguous call to overloaded function
        could be 'int Ccc_file::open(const std::string &)'
        or       'int Ccc_file::open(const Cwin_handle &)'
        while trying to match the argument list '(const char [1])'

[ Voor 12% gewijzigd door .oisyn op 15-03-2003 22:47 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 21-08 17:14
Zaterdag na 12 ben ik misschien niet op m'n scherpst, maar ik meen me te herinneren dat een string literal in sommige gevallen converteerde naar een (non-const) char*.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 13-08 16:46

curry684

left part of the evil twins

MSalters schreef op 16 March 2003 @ 00:13:
Zaterdag na 12 ben ik misschien niet op m'n scherpst, maar ik meen me te herinneren dat een string literal in sommige gevallen converteerde naar een (non-const) char*.
Hoe dan ook is dit way out-of-line:
C++:
1
strcpy("fiets", "bier");

:)

Professionele website nodig?


  • Eelis
  • Registratie: Januari 2003
  • Laatst online: 21-02-2015
.

[ Voor 105% gewijzigd door Eelis op 18-02-2015 19:45 ]


  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Verwijderd schreef op 15 maart 2003 @ 20:17:
eh? Je wilt enerzijds geen extra functies maken, maar wilt ook geen statements aanpassen.

hmm.. ik vraag me af hoe je het dan voor ogen had gehad? Je zult toch echt iets moeten veranderen wil het werken ?
Iets met explicit.
madwizard schreef op 15 maart 2003 @ 20:30:
Zoals hezik al zei zal je toch wat aan moeten passen. Aangezien een HANDLE eigenlijk een void * is zijn er voor char * 2 conversies mogelijk en de een heeft geen hogere prioriteit ofzo dus de call is ambigu.
Je zou de Cwin_handle(HANDLE h) constructor explicit kunnnen maken maar dan moet je je eerste statement toch aanpassen (CreateFile return waarde als parameter ipv rechterkant van een assignment).
Volgens mij is de makkelijkste oplossing nog gewoon de open(HANDLE) een andere naam te geven, bijvoorbeeld attach(HANDLE) (eigenlijk opent de functie het bestand ook niet, want dat is al gedaan).
Hij heette gisteren nog attach, maar omdat detach en close hetzelfde deden heb ik detach maar verwijderd en attach open genoemd.
Maar regel 22 gebruikt toch de constructor van regel 10? En die constructor heeft als argument HANDLE, dus is er geen conversie nodig.

Ik gebruik inderdaad Visual C++ 6 SP last.

  • madwizard
  • Registratie: Juli 2002
  • Laatst online: 26-10-2024

madwizard

Missionary to the word of ska

OlafvdSpek schreef op 16 March 2003 @ 10:05:
Hij heette gisteren nog attach, maar omdat detach en close hetzelfde deden heb ik detach maar verwijderd en attach open genoemd.
Maar regel 22 gebruikt toch de constructor van regel 10? En die constructor heeft als argument HANDLE, dus is er geen conversie nodig.
Er is ook geen conversie nodig nee, maar als je er explicit voorzet kan je niet meer een assignment gebruiken om het object aan te maken. De conversies zitten bij de open method. De ene wil een Cwin_handle&, de andere een string&. Je hebt een const char*, die kan dus ofwel een Cwin_handle worden (in VC dan :) ), of een string. Beide hebben 1 conversiestap nodig en zijn daarmee ambigu. Als je een HANDLE als parameter geeft heb je het probleem niet omdat je daar geen string van kan maken.

www.madwizard.org


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 13-08 16:46

curry684

left part of the evil twins

Explicit werkt alleen voor constructors:
This keyword is a declaration specifier that can only be applied to in-class constructor declarations. An explicit constructor cannot take part in implicit conversions. It can only be used to explicitly construct an object.
Overigens vind ik je class model sowieso vreemd... waarom kies je niet voor deze aanpak:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class Cwin_handle   
{ 
public:
    virtual ~Cwin_handle()
    { CloseHandle(m_Handle); }

protected:     // Kan ook public, maar protected lijkt me beter
    Cwin_handle(HANDLE p_Handle)
    { m_Handle = p_Handle; }

    inline HANDLE Handle() const { return m_Handle; }

private:
    HANDLE m_Handle;
}; 

class Ccc_ioobject : public Cwin_handle
{ 
public:
    explicit Ccc_file(HANDLE p_Handle);

    int Read(void* p_Buffer, int p_Length);
    int Write(void* p_Data, int p_Length);
}; 

class Ccc_file : public Ccc_ioobject
{ 
public:
    Ccc_file(const Ccc_file& p_File);
    Ccc_file(const string& p_FileName); 
}; 

Op deze manier gebruik je je constructors en destructors waar ze voor uitgevonden zijn? :?

Professionele website nodig?


  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Maar door de Cwin_handle constructor explicit te maken los je de dubbelzinnigheid van de open call op.
Alleen werkt dan regel 22 niet meer.

Ccc_file gebruikt niet altijd zijn 'eigen' Cwin_handle, daarom is niet geinherit van Cwin_handle.
En iets als iostream heeft toch ook nog open en close?
Pagina: 1