Community
cancel
Showing results for 
Search instead for 
Did you mean: 
R_Kannan
Beginner
298 Views

Error: operator() will not be called for implicit or explicit conversions

So, I get the following error when compiling a class template.

vectors.h(441): error #597: "Vec3<T>::operator Vec3<T>()" will not be called for implicit or explicit conversions

The offending line is a casting operator for a 3-component vector class:

    operator Vec3() 
    {    return Vec3<double>(x, y, z);                                }

Vec3 is templated on the type of the scalar.

Has anyone come across this and is there a list that tabulates these error codes?

 

0 Kudos
3 Replies
298 Views

Hi Kannan,

I've figured out below test case to help you understand what the issue is:

template <class T>
class A
{
  operator A<float> () const { };  // Cast to A<float>
};

template <class T>
class B
{
  operator B() const { };  // See what is the difference? using B<TYPE> will avoid the warning. What does this mean? cast to type of B, but B is a template and it need to be B<type>.
};

/*
int main() {
   A<int> a;
   A<float> a1=a;

   B<int> b;
   B<float> b1=b;  // cannot work, gcc: error: conversion from 'B<int>' to non-scalar type 'B<float>' requested
}
*/
$ gcc temp.cpp -c
$ icc temp.cpp -c
temp.cpp(10): warning #597: "B<T>::operator B<T>() const" will not be called for implicit or explicit conversions
    operator B() const { };  // See what is the difference? using B<TYPE> will avoid the warning. What does this mean? cast to type of B, but B is a template and it need to be B<type>.
    ^

$ icc temp.cpp -c -Werror
temp.cpp(10): error #597: "B<T>::operator B<T>() const" will not be called for implicit or explicit conversions
    operator B() const { };  // See what is the difference? using B<TYPE> will avoid the warning. What does this mean? cast to type of B, but B is a template and it need to be B<type>.
    ^

compilation aborted for temp.cpp (code 2)
$

This is a warning, and the warning do make sense, you need to specify the type for the template (though gcc will not warn it, it is still worth a warning). If you comment out the "main" part in above code and try to understand the code (yes, GCC will report the error as I mentioned in the comments), you'll know why I said a warning is better, this is cast operator and in class B, the code cannot be used (I cannot think of any case this code can be called/used.) as you'll never have a datatype as "B" (since B is a template, it will always be B<int>, B<float>, B<xxx> etc.) for you to cast to. ICC will told you this warning correctly (this cast operator will not be called, in fact, it cannot be called in any case in my understanding.)

Now, why it is an error in ICC? I think you have used -Werror, which will force warning as errors. :)

Hope it is clear and helpful!

Thanks,

Shenghong

R_Kannan
Beginner
298 Views

Hi Shengong

Thanks, I understand what you're saying and you're right, I'm treating warnings as errors, so #597 was originally a warning.

Now, on to your example. I made the operators public and compiled it with ICC 16.0 in VS/Windows. This is the compiler output from ICC:

1>ConsoleApplication3.cpp(22): warning #597: "B<T>::operator B<T>() const" will not be called for implicit or explicit conversions

1>      operator B() const { };  
1>      ^
1>  
1>ConsoleApplication3.cpp(15): warning #597: "A<T>::operator A<float>() const [with T=float]" will not be called for implicit or explicit conversions
1>      operator A<float> () const { };  
1>      ^
1>            detected during instantiation of class "A<T> [with T=float]" at line 47
1>  
1>ConsoleApplication3.cpp(50): error : no suitable user-defined conversion from "B<int>" to "B<float>" exists
1>      B<float> b1=b; 
1>                  ^
1>  
1>ConsoleApplication3.cpp(15): warning #1011: missing return statement at end of non-void function "A<T>::operator A<float> [with T=int]"
1>      operator A<float> () const { };  
1>                                   ^
1>            detected during instantiation of "A<T>::operator A<float>() const [with T=int]" at line 47
1>  
1>  compilation aborted for ConsoleApplication3.cpp (code 2)

I do understand the error at line 50, this is what you refer to in your post. However, A still produces warning #597 (line 15). 

With MSVC 11, I don't get the warnings, only the error about the casting operator for B not working, which is expected. This is the build output from VC

1>ConsoleApplication3.cpp(50): error C2440: 'initializing' : cannot convert from 'B<T>' to 'B<T>'
1>          with
1>          [
1>              T=int
1>          ]
1>          and
1>          [
1>              T=float
1>          ]
1>          No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called

I then introduce a third class, C:

template <typename T> class C
{
    T x;
public:
    C() : x(0) {}
    C(T x_) : x(x_) { }

    operator C<double> () const
    { std::cout<<__FUNCTION__; // MS specifc
        return C(x); }
};

And the following calling code in main:

  C<int> ic;
  C<double> dc = ic;

This example produces warning #597 with icc:

1>ConsoleApplication3.cpp(32): warning #597: "C<T>::operator C<double>() const [with T=double]" will not be called for implicit or explicit conversions
1>        operator C<double> () const
1>        ^
1>            detected during instantiation of class "C<T> [with T=double]" at line 53

When I run it, the casting operator is indeed called when the variable dc is created. But there is another problem: the implementation of the operator is an endless recursion!!

MSVC traps this potential recursion:

 consoleapplication3.cpp(34): warning C4717: 'C<int>::operator C<double>' : recursive on all control paths, function will cause runtime stack overflow

The fix is to of course specialize the template C before calling the constructor.

    template <typename TT>
    operator C<TT> () const
    { std::cout<<__FUNCTION__;
        return C<TT>(x); }

which produces the desired result and no warnings.

Ram

298 Views

Hi Ram,

Yes, you are correct, the code may be still invalid, but I just intended to show you why it is a warning of ICC for B (which is very similiar like the case you provided for Vec3, you are not specify the type of the template there) and the warning do make sense.

But you are correct, when I did more testing around, I do see similiar behaviour you mentioned and there seems like be an some issues.

Regarding your C class code, yes, that is more complete and better code.

Below testing are under windows to keep consistent with yours (may be similiar on Linux), and summarize 2 of the warning issues I found (which may need fix/improve from ICC side, I've reported our findings to dev team.) But again, for the original code  you posted (or the class B code), this warning may makes sense, as it do will not be called in any case. :)

#include <iostream>

#ifdef ISSUE1
template <class T>
class A
{
public:
  operator A<float> () const {
    std::cout<<"cast to A<float>"<<std::endl;
    return A<float>();
  };  // Cast to A<float>
};
#endif

#ifdef ISSUE2
template <class T>
class A
{
public:
  operator A<float> () const {
    std::cout<<"cast to A<float>"<<std::endl;
    return A();
  };  // Cast to A<float>
};
#endif

int main() {
   A<int> a;
   A<float> a1=a;	// trigger call cast operator
}

/*
Issue1:
Reproduce:
=================================
On Windows:
: cl test.cpp /nologo /EHsc /DISSUE1
test.cpp
You are using an Intel supplied intrinsic header file with a third-party compile
r.

: test.exe
cast to A<float>

: icl test.cpp /nologo /EHsc  /DISSUE1
test.cpp
test.cpp(7): warning #597: "A<T>::operator A<float>() const [with T=float]" will
 not be called for implicit or explicit conversions
    operator A<float> () const {
    ^
          detected during instantiation of class "A<T> [with T=float]" at line 1
5


: test.exe
cast to A<float>

:
On Linux:
$ icc temp.cpp -DISSUE1
temp.cpp(8): warning #597: "A<T>::operator A<float>() const [with T=float]" will not be called for implicit or explicit conversions
    operator A<float> () const {
    ^
          detected during instantiation of class "A<T> [with T=float]" at line 29

$ ./a.out
cast to A<float>
$ g++ temp.cpp -DISSUE1
$ ./a.out
cast to A<float>
$
=================================

Issue:
=================================
This warning should not be reported here and in fact, the cast operator will be called correctly from the runing result!!!
No warning from MS compiler or GCC compiler.
=================================

Issue2:
Reproduce:
=================================
: icl test.cpp /nologo /EHsc /DISSUE2
test.cpp
test.cpp(20): warning #597: "A<T>::operator A<float>() const [with T=float]" wil
l not be called for implicit or explicit conversions
    operator A<float> () const {
    ^
          detected during instantiation of class "A<T> [with T=float]" at line 2
9


: cl test.cpp /nologo /EHsc /DISSUE2
test.cpp
You are using an Intel supplied intrinsic header file with a third-party compile
r.
test.cpp(23) : warning C4717: 'A<int>::operat
or A<float>': recursive on all control paths, function will cause runtime stack
overflow

:
run test.exe, it is an endless loop.
=================================

Issue:
=================================
Wrong/bad warning message from ICC, good warning from MS compiler.
On Linux, no any warning with GCC. At least, ICC should remove the waring (this is issue 1 then), if possible, catch the issue like MS compiler.
=================================
*/

Thanks,

Shenghong

Reply