Код ниже адаптирован из ответа здесь: https://stackoverflow.com/a/17579889/352552
Моя цель при задании этого вопроса - попытаться лучше понять, как C ++ обрабатывает разрешение типов вокруг зависимых типов по сравнению с тем, что считается в текущей реализации, и поэтому не нуждается в квалификаторе typename
. Я получаю противоречивые результаты от разных компиляторов, поэтому я пришел сюда в поисках более канонического ответа.
Рассмотрим этот код
#include <iostream>
struct B {
typedef int result_type;
};
template<typename T>
struct C {
};
template<>
struct C<float> {
typedef float result_type;
};
template<typename T>
struct D : B, C<T> {
std::string show() {
//A) Default to current instantiation - ignore dependent type, even if one exists, or so I hope
D::result_type r1;
//B) What **exactly** does typename add, here?
//typename D::result_type r1;
return whichType(r1);
}
std::string whichType (int val){
return "INT";
}
std::string whichType (float val){
return "FLOAT";
}
};
int main() {
D<std::string> stringD;
D<float> floatD;
std::cout<<"String initialization "<<stringD.show()<<std::endl;
std::cout<<"Float initialization "<<floatD.show()<<std::endl;
}
строка A) в show()
, если я правильно понимаю, говорит компилятору использовать текущую реализацию, поэтому я должен получить INT INT. На GCC я делаю. Все идет нормально.
Строка B, опять же, если я правильно понимаю, должна либо сказать компилятору рассмотреть зависимые типы, что приведет к ошибке в этой строке из-за неоднозначности; или, если это означает, что только учитывает зависимые типы, я должен получить INT FLOAT. На GCC я тоже получаю INT INT. Почему?
Запуск этого на Clang.
Строка A вообще не компилируется.
ошибка: нет типа с именем 'result_type' в 'D'; Вы имели в виду просто 'result_type'? D :: result_type r1;
сброс D::
действительно дает INT INT.
Должен ли он скомпилироваться, или Clang здесь правильный?
Строка B действительно дает ошибку по неопределенности
ошибка: элемент 'result_type' найден в нескольких базовых классах разных типов, имя типа D :: result_type r1
Может ли кто-нибудь здесь с уверенностью сказать, какой компилятор (если есть!) Канонически корректен и почему?
Предполагая, что Clang верен, это может означать, что
MyType::F
недопустимо для ссылки на тип из текущего экземпляра, если он существует для базового типа; это допустимо, только если тип определен в этом классе. Т.е. добавление
typedef double dd;
до D
, а затем
D::dd d = 1.1;
std::cout<<d;
в show
будет работать нормально, что действительно так.
* * Тысяча шестьдесят-два Кроме того,
typename D::sometype
, кажется, означает рассмотрение зависимых типов, но не исключительно, и поэтому ожидайте ошибок, если такой тип будет определен в нескольких местах, либо в текущем экземпляре, либо в зависимости от параметра шаблона.
Но опять же, все это предполагает, что поведение Clang является правильным в соответствии со спецификацией, с которой я не могу говорить.
Ссылка на GCC Repl, который я использовал:
https://wandbox.org/
Ссылка на реплан Clang, который я использовал:
https://repl.it/languages/cpp11