Шаблоны функций не могут быть специализированы на C ++, точка.
Неважно, являются ли они членами шаблона, специализация шаблонов функций не допускается. Обычно при использовании типов аргументов для вывода аргументов шаблона перегрузка выполняет ту же специализацию, поэтому специализация для функций (и связанная с этим дополнительная сложность в разрешении перегрузки и т. Д.) Не считалась необходимой.
У вас, однако, нет аргументов для вывода, и вы бы создали шаблоны вручную. Нет,
DataStructure::DerivedIterator1 i = dataStructure.Begin();
будет не работать так, как вы написали код, поскольку вывод типа, как и разрешение перегрузки, выполняется только для аргументов, а не для ожидаемого возвращаемого значения. Вы должны написать:
DataStructure::DerivedIterator1 i = dataStructure.Begin<DataStructure::DerivedIterator1>();
и это имеет нулевое преимущество по сравнению с:
DataStructure::DerivedIterator1 i = dataStructure.BeginIterator1();
Однако первое выражение может быть сделано для работы с некоторыми волшебствами. Сначала вы должны определить BeginIterator1
и BeginIterator2
, а затем сделать временный выбор, чтобы позднее решить, какой из них построить:
class DataStructure {
...
class BeginIteratorConstructor {
DataStructure &dataStructure;
public:
BeginIteratorConstructor(DataStructure &ds) : dataStructure(ds) {}
operator DerivedIterator1() { return dataStructure.BeginIterator1(); }
operator DerivedIterator2() { return dataStructure.BeginIterator2(); }
};
BeginIteratorConstructor Begin() { return BeginIteratorConstructor(*this); }
...
};
Теперь dataStructure.Begin()
вернет временное что-то, что вызовет BeginIterator1
, если вы приведете его к DerivedIterator1
или вызову BeginIterator2
, когда вы приведете к DerivedIterator2
. Если вы передадите его чему-то, где компилятор не сможет решить, к какому из них привести данные, он умрет либо из-за неоднозначной перегрузки, либо из-за того, что BeginIteratorConstructor
на самом деле не является итератором, и вам придется явно приводить его.
(Вы должны тщательно сделать как можно больше BeginIteratorConstructor
приватных данных, но я не уверен, насколько далеко компилятор позволит вам зайти, поэтому вам придется немного поэкспериментировать)