Приведение класса шаблона с оператором T* при передаче в качестве аргумента T* шаблона функции
Предположим, у меня есть такой шаблон функции:
template<class T>
inline
void
doStuff(T* arr)
{
// stuff that needs to use sizeof(T)
}
Потом в другой .h
У меня есть шаблон класса Foo
который имеет:
public: operator T*() const;
Теперь я понимаю, что это разные Ц. Но если у меня есть переменная Foo<Bar> f
в стеке единственный способ привести его к любому указателю - это вызвать operator T*()
, Тем не менее, если позвонить doStuff(f)
GCC жалуется, что doStuff
не может взять Foo<Bar>
вместо автоматического использования оператора T*()
принуждать к Bar*
а затем специализировать шаблон функции с Bar
как T
,
Могу ли я что-нибудь сделать для работы с двумя шаблонами? Или аргумент функции шаблона должен быть реальным типом указателя, или класс шаблона с оператором приведения должен быть передан в не шаблонную функцию?
5 ответов
GCC правильно. В аргументах шаблона учитываются только точные совпадения, а преобразования типов - нет. Это связано с тем, что в противном случае необходимо учитывать бесконечное (или, по крайней мере, экспоненциальное) количество преобразований.
Если Foo
template<typename T> inline void doStuff(const Foo<T>& arr) {
doStuff(static_cast<T*>(arr));
}
Если у вас есть эта проблема с большим количеством шаблонов, этот должен исправить это:
#include <boost/type_traits/is_convertible.hpp>
#include <boost/utility/enable_if.hpp>
template<template <typename> class T, typename U> inline typename boost::enable_if<typename boost::is_convertible<T<U>, U*>::type>::type doStuff(const T<U>& arr) {
doStuff(static_cast<U*>(arr));
}
Это немного многословно, хотя;-)
Это может стоить попробовать:
doStuff<Bar>(f);
Я думаю, что это заставит компилятор ожидать, что T* будет Bar*, а затем использовать оператор Foo T*() для выполнения приведения, но я не могу сказать, что пробовал это.
Идея Леона, вероятно, лучшая. Но в крайнем случае, вы также можете явно вызвать оператор приведения:
doStuff(static_cast<Bar*>(f));
Ну, T* не является отдельным типом от T в том смысле, в каком вы думаете. Указатель является классификатором типа. Я не уверен, что стандарт говорит об этом, но я бы сказал, что, поскольку переменная уже имеет тип T, она не пытается преобразовать снова. Если вы хотите сделать что-то нестандартное, чтобы получить указатель, перегрузите оператор &.
Я не уверен, почему преобразование не работает, но вы могли бы использовать перегрузку, чтобы решить проблему
template
inline
void
doStuff(T& arrRef)
{
doStuff(&arrRef);
}