12

Consider this example:

struct B { operator int(); };

template<class T>
struct X:B
{
    using B::operator T;
};

GCC accepts the code, while Clang and MSVC rejects it. Which is correct?

Note that if the base type is dependent, all the compilers accept the code:

template<class T>
struct B { operator T(); };

template<class T>
struct X:B<T>
{
    using B<T>::operator T;
};
Jamboree
  • 5,139
  • 2
  • 16
  • 36
  • 1
    If you make `operator int()` in `B` a templated conversion function (e.g. `template operator T();`) it works, and if you specialize this for `int`, it also works and call the specialization whereas as far as I understand, the standard forbid it (*"Since specializations of member templates for conversion functions are not found by name lookup, they are not considered when a using-declaration specifies a conversion function (14.5.2)."*). Also, clang is able to find `operator T` if you call it in a member function, so I think gcc is right. – Holt Jul 27 '16 at 09:51

2 Answers2

3

I think GCC is right, in §7.3.3/1, we can find:

The set of declarations introduced by the using-declaration is found by performing qualified name lookup (3.4.3, 10.2) for the name in the using-declaration, excluding functions that are hidden as described below.

I don't see any reason why operator T would not be found, actually:

template<class T>
struct X: B {
    T f () { return B::operator T; }
};

...compiles fine with g++ and clang (did not test on MSVC).

I cannot find anything in the standard specific to conversion functionsfor qualified name lookup except:

Since specializations of member templates for conversion functions are not found by name lookup, they are not considered when a using-declaration specifies a conversion function (14.5.2).

But B::operator int is not a specialization of a member function template, so it should not be taken into account by the above.

Holt
  • 36,600
  • 7
  • 92
  • 139
-1

Hmm... Gcc does not like the first one either. It compiles unless you try to create instance of struct X with template parameter other than int. What would be the meaning of X<double>::operator double()? Class B does not have such an operator but we would try to use it.

To sum up: MSVC and clang try to warn you beforehand (even if you don't do anything veeeery stupid right now) while gcc does produce an error only if you attempt to create something incorrect. This does not compile in gcc (5.3.0):

#include <iostream>

struct B { operator int(); };

template<class T>
struct X:B
{
    using B::operator T;
};

int main(int argc, char **argv)
{
    X<char> x;
    std::cout << "Hello!" << std::endl;
    return 0;
}
Lehu
  • 761
  • 4
  • 14
  • It does not mean GCC is wrong. If you make the conversion operator templated in `B`, and you specialize it for `int`, all compilers will be happy, but your program will not compile (fails at linkage) for any other type than `int` (with any compiler). – Holt Jul 27 '16 at 10:01
  • @101010 That is exactly what I have written: _It compiles unless you try to create instance of struct X with template parameter other than `int`._ – Lehu Jul 27 '16 at 10:01
  • @Holt I've never said that GCC is wrong. I know that, templated operator works. But the question was: _Why templated operator in B works, and operator int() in B works for GCC and does not work for MSVC and clang?_ I believe that I answered that. Moreover if I take code from my answer and change X to X it still does not compile im MSVC but it starts to compile in GCC. – Lehu Jul 27 '16 at 10:05
  • 1
    @Lehu Sorry for the riddle kind of comment. What I mean is that you don't answer the OP's question as to which compiler exhibits standard behaviour. – 101010 Jul 27 '16 at 10:11
  • 1
    @Lehu There is a difference between a compiler that fails to instantiate a template due to ill-formed code (gcc with `X `) and a compiler that fails when "defining" the template (clang). OP's asks if the standard specifies former or later behavior for the given code. – Holt Jul 27 '16 at 10:36
  • Well... I just took another look at the question and it seems that I indeed strayed a bit from the topic. Just heat of the moment :) . – Lehu Jul 27 '16 at 10:39
  • Hmm... I just looked at the standard and I can't find anything which could be simply applied here. But I would say that gcc behaviour is closer to the standart intentions but it's just my opinion... – Lehu Jul 27 '16 at 10:48
  • This is not an answer. – underscore_d Jul 27 '16 at 11:40
  • Looks like an answer to me. It implies that all three compilers are conformant. Whether or not it is a _correct_ answer is another matter. – Oktalist Jul 27 '16 at 11:44