1. Во-первых, полезное исправление: вы сказали «... когда я включаю тип возврата». Я думаю, что вы, возможно, неправильно поняли, что делает <int>
часть testclass1::foo<int>(2)
. Он не обязательно указывает тип возвращаемого значения, он просто предоставляет значение для аргумента шаблона «A».
Вы могли бы выбрать использование A в качестве типа возврата, но у вас есть тип возврата, жестко закодированный как "bool".
По сути, для функции, которую вы написали, вам всегда нужно иметь <>
для вызова. C ++ позволяет вам опустить <args>
в функции, когда тип может быть выведен из аргументов функции; чтобы заставить это сделать, вы должны использовать аргумент типа A в аргументах вашей функции. Например, если вы объявили функцию таким образом, вы могли бы вызвать ее без <>
:
template<class A> static bool foo(A i);
В этом случае это можно было бы назвать "foo (2)", и это вывело бы A из числа два в "int".
С другой стороны, нет никакого способа заставить его выводить что-либо на основе того, для чего вы назначаете функцию. Для вывода аргументов шаблона он смотрит только на аргументы функции, а не на то, что делается с результатом вызова функции. Итак, в:
bool b = testclass1::foo(2);
Нет способа заставить его выводить "bool" из этого, даже если вы сделали A типом возврата.
Так почему же компилятор просто не скажет вам "вам нужно использовать <>
в функции"? Даже если вы объявили foo один раз как функцию шаблона, вы могли бы также перегружать его не версией шаблона. Таким образом, компилятор не просто автоматически предполагает, что вы пытаетесь вызвать функцию шаблона, когда вы оставляете <>
вне вызова. К сожалению, НЕ предполагая, что вы вызываете template-foo и не видите никакого другого объявления для foo, компилятор возвращается к старому правилу стиля C, где для функции, которая принимает int и возвращает int, на очень старом диалекте C вам не нужно объявлять такого рода, прежде чем использовать его. Таким образом, компилятор предположил, что это именно то, что вы хотели, но затем он заметил, что template-foo и old-crufty-C-foo оба принимают параметр int, и понимает, что он не сможет определить разницу между ними. Итак, он говорит, что вы не можете объявить foo. Вот почему компиляторы C ++ печально известны тем, что выдают плохие сообщения об ошибках - к тому времени, когда об ошибке сообщается, компилятор, возможно, полностью сошел с рельсов и говорит о чем-то, что на три-четыре уровня удалено из вашего реального кода!
2. Да, вы совершенно правы.
3. Я считаю, что ссылки на C ++ и технические документы, которые IBM делает доступными в Интернете, являются наиболее информативными. Вот ссылка на раздел о шаблонах: C ++ Templates