0

Consider following example.

The Idea is to exploit overloading operator= to automatically select one of multiple function calls from the required type (LinkKey or AttrKey). Currently, the programmer has to decide which one to call, which is prone to errors, and if it happens, very hard to debug.

Unfortunately it appears as if the compiler is unable to differentiate the calls, because the base type is always an int (the C2535 indicates this).

Is there any chance to make this work without doing anything to the LinkKey and AttrKey definitions, as that would be a major change?

The build environment is MSVC 2012.

** Update **

Changed to conversion operators. It was initially my assumption that an assignment happens, but know I know that the initialization is a special case.

The issue with both typedefs resolving to the same base type remains.

** Update 2**

I will scrap this as apparently it is not possible without modifiying the type definitions, and the inclusion of third party libraries.

#include <string>
#include <random>

//  This is an example how the legacy interface works. It does not matter what it does internally. This is stuff that shall not be changed if possible.

typedef int LinkKey;
typedef int AttrKey;


class Store
{
public:

    LinkKey LookupLinkKey( std::string key )
    {       
        // random value is good enough for this example
        return rand();
    }

    AttrKey LookupAttrKey( std::string key )
    {       
        // random value is good enough for this example
        return rand();
    }   

};


// This is my extension, that should protect vs. the failureTest shown below

class Key
{
public:
    Key( std::string keystr )
        : m_keystr( keystr )
    {}

    static void SetStore( Store* pStore )
    {
        s_pStore = pStore;
    }

    //LinkKey Key::operator= (  const Key& key )
    //{         
    //  LinkKey lk = s_pStore->LookupLinkKey( key.m_keystr );
    //  return lk;
    //}

    //AttrKey Key::operator= (  const Key& key ) // C2535: 'LinkKey      Key::operator=(const Key&)' member function already defined or declared
    //{
    //  AttrKey ak = s_pStore->LookupAttrKey( key.m_keystr );
    //  return ak;
    //}

    operator LinkKey() const
    {           
        LinkKey lk = s_pStore->LookupLinkKey( m_keystr );
        return lk;
    }

    operator AttrKey() const 
    {
        AttrKey ak = s_pStore->LookupAttrKey( m_keystr );
        return ak;
    }

private:
    std::string& m_keystr;

    static Store* s_pStore;
};

Store* Key::s_pStore;

// Usage
void main( int argc, char* argv )
{
    Store s;
    Key::SetStore( &s );

    LinkKey lk = Key("Link"); // C2440: cannot convert from 'Key' to 'LinkKey'
    AttrKey ak = Key("Attribute"); // C2240: cannot convert from 'Key' to 'AttrKey'


    LinkKey failureTest = s.LookupAttrKey("Foo"); // Ewwwwww...
}
antipattern
  • 743
  • 1
  • 9
  • 20
  • 1
    You could use [BOOST_STRONG_TYPEDEF](http://www.boost.org/doc/libs/1_57_0/libs/serialization/doc/strong_typedef.html). – el.pescado - нет войне Jan 20 '17 at 11:22
  • Interesting. I will have a look at it. – antipattern Jan 20 '17 at 11:24
  • Why are you passing in `std::string key` and not using it? Also perhaps `const std::string& key` would be better – Ed Heal Jan 20 '17 at 11:26
  • 1
    IDK -- This usage of `operator =` could silently bite you bad. – PaulMcKenzie Jan 20 '17 at 11:27
  • @Ed heal I've stripped the real logic there because it adds nothing to the question. The const ref would obviously be better, but I do not want to touch that as it is legacy code. – antipattern Jan 20 '17 at 11:27
  • I suggest reworking your example, it's incomplete. It contains basic errors. The error you are getting here `LinkKey lk = Key("Link");` is because there is missing a conversion operator, not `operator=`. Did you strip it down too much? You will also have problems discriminating overload based on the return type only. – luk32 Jan 20 '17 at 11:31
  • The `operator =`, when given a reference to the type that is copied, should be doing a copy (either a deep copy or some sort of reference count). Any other usage IMO is abuse of that operator. Otherwise be prepared for weird behavior and long debugging sessions if the program becomes more complex. – PaulMcKenzie Jan 20 '17 at 11:32
  • @PaulMcKenzie thanks for pointing this out. I assumed there was an assignment happening (because =). – antipattern Jan 20 '17 at 11:49
  • @antipattern Warning -- Adding conversion operators makes the program even more unpredictable as to what will happen at runtime, let alone may cause failures at compile time due to ambiguities. That's why you don't see `std::string` have a `char *` conversion operator, and instead `c_str()` function is implemented. – PaulMcKenzie Jan 20 '17 at 11:50
  • Alright. I understand the problems now, and will not pursue this any further. Too bad. – antipattern Jan 20 '17 at 11:54

0 Answers0