Advertisement Jump to content
Sign in to follow this  
Kostikov Stas

Strange behavior of operator type

This topic is 1784 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I wanted to make that my class can be converted to custom type: 

#include <iostream>
#include <string>


class SomeClass
{
public:
      template< typename type >
      operator type() 
      {
          return type();
      }
};


int main()
{
    
    std::cout << "Hello, world!\n";
    
    SomeClass sc;
    std::string str = sc;
    
    return 0;   
}

This code is correct, compiled on gcc, vc 2010 but when i tried to build it on 2012 i get this error:

 

1>e:\test\operatortest\operatortest.cpp(22): error C2440: 'initializing' : cannot convert from 'SomeClass' to 'std::basic_string<_Elem,_Traits,_Alloc>'
1>          with
1>          [
1>              _Elem=char,
1>              _Traits=std::char_traits<char>,
1>              _Alloc=std::allocator<char>
1>          ]
1>          No constructor could take the source type, or constructor overload resolution was ambiguous
 
I missed something? Is there is some change in standart ? Or it just bug in compiler?
Edited by Kostikov Stas

Share this post


Link to post
Share on other sites
Advertisement

I think this is a valid error.

 

Imagine if you had non-templated conversion operators on SomeClass - one for std::string, one for char, one for const char*. It would make sense then that this error appeared since std::string can be constructed from any of these types.

 

Since your conversion operator is templated, the type cannot be deduced disambiguously.

 

A template conversion operator makes me shudder for some reason. How would this be extended to real use, through specializations?

Share this post


Link to post
Share on other sites

Well i'm not sure where i have to put here static_cast smile.png

class SomeClass
{
public:
	operator std::string()
	{
		return "";
	}
    template< typename type >
    operator type() 
    {
		return type();
    }
};

This code doesn't compile. But this:

class SomeClass
{
public:
	operator std::string()
	{
		return "";
	}
};

Compile and work fine.  

 

Original code is correct by syntax. As i say it's compiled on gcc (new versions was tested). Compiled on VC 2010. And failed only on VC 2012. I can make side function for string case . But my question is can i fix operator type so he can work correctly?

Share this post


Link to post
Share on other sites

I think Ectara meant static cast in the assignment:

 

SomeClass sc;

std::string str = static_cast<std::string>(sc);

 

I'm confused though. Why would you have a class that can be converted to absolutely any type? Your current code just returns a default constructed instance of the type. How can you make this useful by actually returning any type at all with something meaningful from SomeClass?

Share this post


Link to post
Share on other sites
There are good reasons variant types aren't implemented this way. How are you actually storing the data a internally?

You are trying to deduce the type from the left hand side of the expression which is always going to end up ambiguous.

I'd suggest a templated get method where you supply the type you are extracting explicitly when you access rather than a conversion operator.

Share this post


Link to post
Share on other sites

Further to your PM, I don't see much point in discussing this privately. Better any discussion in an open forum where others can participate or benefit.

 

You said in your PM that this approach is safe and efficient. Be that as it may, a fundamental thing in C++ is that types are not deduced from the left-hand side of an expression. For example:

class Variant
{
public:
    operator std::string() const { /*...*/ }
    operator int() const { /*...*/ }
};

class SomeType
{
public:
    SomeType(int i){ }
    SomeType(std::string s){ }
};

void f(Variant v)
{
    int i = v; // fine, int does not have std::string constructor
    SomeType t = v; // ambigous - should we use int or std::string?
}

The problem you are having, regardless of whether it works on some versions of some compilers or not, is that C++ is not designed to deduce types from the assignment target in an assignment expression.

 

Something you can do is:

class Variant
{
public:
    template<class T> T get(){ /*...*/ }
};

void f(Variant v)
{
    int i = v.get<int>();
    std::string s = v.get<std::string>();

    // or to reuse SomeType above

    SomeType a = v.get<int>();
    SomeType b = v.get<std::string>(); // no longer ambigous
}

The point being that the type is deducable from the right-hand side of the expression, so the ambiguity is resolved.

 

I remain interested to know how you store the underlying data in your variant class in a way that is flexible enough to actually require templated conversion operators, rather than just a specific set of allowed types, but it doesn't change the fact that implicit conversion is not a good way to extract types from a variant.

Edited by Aardvajk

Share this post


Link to post
Share on other sites

Mine code isn't variant type. It's much different and I don't see a point to discuss it here. My question was why code writen according standart  isn't compiled. 

Not why i shouldn't use this code. And i suggest to stay with topic question.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!