2016-07-27 11 views
12

Рассмотрим следующий пример:Используется ли `using Base :: operator T`, где` T` является параметром типа шаблона?

struct B { operator int(); }; 

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

GCC принимает код, в то время как Clang и MSVC отвергает его. Что именно?

Обратите внимание, что если базовый тип зависит, все составители принимают код:

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

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

Если вы делаете 'operator int()' в 'B' шаблонизированной функцией преобразования (например,' template operator T(); '), он работает, и если вы специализируетесь на этом для' int', он также работает и вызывается специализация, тогда как, насколько я понимаю, стандарт запрещает ее (* «Так как специализации шаблонов членов для функций преобразования не найдены при поиске по имени, они не учитываются, когда декларация использования указывает функцию преобразования (14.5.2) . "*). Кроме того, clang может найти 'operator T', если вы вызываете его в функции-члене, поэтому я думаю, что gcc прав. – Holt

ответ

3

Я думаю, GCC является правильным, в § 7.3.3/1, можно найти:

Набор деклараций ВНЕСЕН Использование-декларация определяется путем выполнения квалифицированного поиска имени (3.4.3, 10.2) для имени в объявлении использования, за исключением функций, которые скрыты, как описано ниже.

Я не вижу никаких причин, почему operator T не будет найден, на самом деле:

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

... компилирует хорошо с г ++ и лязг (не испытать на MSVC).

Я не могу найти что-либо в стандартном специфична для преобразования functionsfor квалифицированного имени поиска, за исключением:

С специализациями шаблонов членов для функций преобразования не найдены поиском имен, они не рассматривается при использовании декларирования определяет функцию преобразования (14.5.2).

Но B::operator int не является специализацией по шаблону функции-члена, поэтому его не следует принимать во внимание вышеизложенным.

-1

Хм ... Gcc не нравится первый либо. Он компилируется, если вы не попытаетесь создать экземпляр struct X с параметром шаблона, отличным от int. В чем смысл X<double>::operator double()? Класс B не имеет такого оператора, но мы бы попытались его использовать.

Подводя итог: MSVC и clang пытаются предупредить вас заранее (даже если вы сейчас не делаете ничего глупого), а gcc создает ошибку, только если вы попытаетесь создать что-то неправильное. Это не компилируется в 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; 
} 
+0

изменить 'X x;' to 'X x;' ..........;) – 101010

+0

Это не значит, что GCC ошибочен. Если вы делаете оператор преобразования templated в 'B', и вы его специализируете на' int', все компиляторы будут довольны, но ваша программа не будет компилироваться (сбой при связывании) для любого другого типа, чем 'int' (с любым компилятором). – Holt

+0

@ 101010 Это именно то, что я написал: _It компилируется, если вы не пытаетесь создать экземпляр struct X с параметром шаблона, отличным от 'int'._ – Lehu