В то время как экспериментирование немного с C++ обрабатывает по шаблону, мне удалось произвести этот простой код, для которого вывод отличается, чем я ожидал согласно своему пониманию правил C++.
void bar(double d)
{
std::cout << "bar(double) function called" << std::endl;
}
template void foo(T t)
{
bar(3);
}
void bar(int i)
{
std::cout << "bar(int) function called" << std::endl;
}
int main()
{
foo(3);
return 0;
}
Когда я компилирую этот код в VC ++ Экспресс 2008 года, функция bar(int)
назван. Это было бы поведением, я буду ожидать если bar(3);
в шаблоне тело зависело от шаблонного параметра. Но это не. В правиле, которое я нашел здесь, говорится, что "Стандарт C++ предписывает, чтобы все имена, которые не зависят от шаблонных параметров, были связаны со своими существующими определениями при парсинге шаблонной функции или класса". Я неправильно, то "существующее определение" bar
при парсинге шаблонной функции foo
определение void bar(double d);
? Почему это не имеет место, если я неправ. Нет никаких предописаний bar
в этой единице компиляции.
Это действительно ошибка компилятора. Было известно, что проблема существует в VS2005 и ранее (я использую блог Blogspot в качестве записной книжки для подобных случаев, см. 1.3 здесь ). Судя по всему, он присутствует и в VS2008.
Вы можете протестировать его с помощью следующего простого кода
int bar(double d) { return 0; }
template <typename T> void foo(T t) {
int i = bar(3);
}
void bar(int i);
int main() {
foo(3);
}
Этот код хорошо сформирован (вы можете скомпилировать его с помощью компилятора Comeau Online), но я уверен, что VS подавится им, потому что VS неправильно реализует двухэтапный поиск в этом случае.
AndreyT прав. На самом деле, ваш код практически идентичен примеру из стандарта (§14.6.3/1):
void g(double);
void h();
template<class T> class Z {
public:
void f() {
g(1); //calls g(double)
h++; //ill-formed: cannot increment function;
// this could be diagnosed either here or
// at the point of instantiation
}
};
void g(int); // not in scope at the point of the template
// definition, not considered for the call g(1)