Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overloading conversion operator template

Tags:

c++

Consider the following simple example

struct C
{
    template <typename T> operator T () {return 0.5;}
    operator int () {return 1;}
    operator bool () {return false;}
};

int main ()
{
    C c;
    double x = c;
    std::cout << x << std::endl;
}

When compiled with Clang, it gives the following error

test.cpp:11:12: error: conversion from 'C' to 'double' is ambiguous
    double x = c;
           ^   ~
test.cpp:4:5: note: candidate function
    operator int () {return 1;}
    ^
test.cpp:5:5: note: candidate function
    operator bool () {return false;}
    ^
test.cpp:3:27: note: candidate function [with T = double]
    template <typename T> operator T () {return 0.5;}
                          ^
1 error generated.

Other compilers generate similar errors, e.g., GCC and Intel iclc

If I remove operator int and operator bool. It compiles fine and work as expected. If only remove one of them, that is keep the template operator and say operator int, then the non-template version is always chosen.

My understanding is that only when the template and non-template overloaded functions are equal in the sense that they are both perfect match or both require the same conversion sequence, the non-template version will be preferred. However in this case, it appears that the compiler does not see the operator template as a perfect match. And when both the bool and int overloading are present, then naturally it considers they are ambiguous.

In summary, my question is that why the operator template is not considered a perfect match in this case?

like image 210
Yan Zhou Avatar asked Feb 20 '13 18:02

Yan Zhou


People also ask

What is operator overloading explain conversion?

The operator overloading defines a type conversion operator that can be used to produce an int type from a Counter object. This operator will be used whenever an implicit or explict conversion of a Counter object to an int is required. Notice that constructors also play a role in type conversion.

What is a conversion operator C++?

Conversion Operators in C++ C++ supports object oriented design. So we can create classes of some real world objects as concrete types. Sometimes we need to convert some concrete type objects to some other type objects or some primitive datatypes. To make this conversion we can use conversion operator.

What is the syntax of operator overloading?

When we overload the binary operator for user-defined types by using the code: obj3 = obj1 + obj2; The operator function is called using the obj1 object and obj2 is passed as an argument to the function.

What is operator overloading in C++? *?

It's a type of polymorphism in which an operator is overloaded to give it the user-defined meaning. C++ allows us to specify more than one definition for a function name or an operator in the same scope, which is called function overloading and operator overloading, respectively.


1 Answers

Let's break this down into two different problems:

1. Why does this generate a compiler error?

struct C
{
    operator bool () {return false;}
    operator int () {return 1;}
};

As both int and bool can be implicitly converted to double, the compiler can not know which function it should use. There are two functions which it could use and neither one takes precedence over the other one.

2. Why isn't the templated version a perfect match?

struct C
{
    template <typename T> operator T () {return 0.5;}
    operator int () {return 1;}
};

Why is operator int() called when requesting a double?

The non-template function is called because a non-template function takes precedence in overload resolution. (Overloading function templates)

EDIT: I was wrong! As Yan Zhou mentioned in his comment, and as it is stated in the link I provided, a perfect match in the templated function takes precedence over the non-templated function.

I tested your code (compiled with g++ 4.7.2), and it worked as expected: it returned 0.5, in other words, the templated function was used!

EDIT2: I now tried with clang and I can reproduce the behaviour you described. As it works correctly in gcc, this seems to be a bug in clang.

like image 57
Misch Avatar answered Oct 16 '22 15:10

Misch