Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Template argument type deduction by conversion operator

I see example from the C++ 11 Standard (n3337, 14.8.2.3/7)

struct A {
template <class T> operator T***();
};
A a;
const int * const * const * p1 = a; // T is deduced as int, not const int

and try to reproduce it by different compilers. I changed the example a little by adding a declaration with type T in a conversion function

struct A {
    template <class T> operator T***()
    {
        T t;  //if T==const int, then it is error (uninitialized const)
        return nullptr;
    }
};
A a;
const int * const * const * p1 = a;

int main(){}

All the compilers (VS2014, gcc 5.1.0 and clang 3.5.1) give an error in the declaration of "t", which means T is deduced as const int. Why is that? Is it some extension?

like image 512
Denis Avatar asked May 11 '15 16:05

Denis


1 Answers

This was covered by CWG issue #349, opened by a developer of the EDG C++ front end (which apparently deduces int, not const int):

We ran into an issue concerning qualification conversions when doing template argument deduction for conversion functions.

The question is: What is the type of T in the conversion functions called by this example? Is T "int" or "const int"?

If T is "int", the conversion function in class A works and the one in class B fails (because the return expression cannot be converted to the return type of the function). If T is "const int", A fails and B works.

Because the qualification conversion is performed on the result of the conversion function, I see no benefit in deducing T as const int.

In addition, I think the code in class A is more likely to occur than the code in class B. If the author of the class was planning on returning a pointer to a const entity, I would expect the function to have been written with a const in the return type.

Consequently, I believe the correct result should be that T is int.

struct A {
  template <class T> operator T***() {
      int*** p = 0;
      return p;
  }
};

struct B {
  template <class T> operator T***() {
      const int*** p = 0;
      return p;
  }
};

int main()
{
  A a;
  const int * const * const * p1 = a;
  B b;
  const int * const * const * p2 = b;
}

We have just implemented this feature, and pending clarification by the committee, we deduce T as int. It appears that g++ and the Sun compiler deduce T as const int.

This only brought the quoted paragraph into existence (it didn't exist in C++03!), and was presumably overlooked by compiler developers.

like image 177
Columbo Avatar answered Nov 05 '22 20:11

Columbo