У меня есть шаблон класса foo
template <typename Item>
class foo
{
void method()
{
// ...
}
}
что мне нужно, это изменить реализацию метода, основанного на типе элемента, на основе, если функция скажет unsigned int hasher(const Item& item)
существует.
Мой вопрос — как это технически возможно, и если нет, то как я мог бы организовать код, чтобы иметь это?
Обратите внимание, что для алгоритма важна производительность, и я ищу решения, которые позволят компиляторам решать разницу времени компиляции.
Вам необходимо применить шаблон политики, взгляните на:
http://en.wikipedia.org/wiki/Policy-based_design
также
Шаблоны C ++
В течение многих лет не касался кода на C ++, поэтому не могу написать вам пример на месте [ну, может, я смогу, но результаты были бы веселыми], но, как указано в этот ответ силы, которые вы ищете, можно найти в SFINAE
// Macro helper to create traits
#define HAS_TEMPLATED_FUNC(traitsName, funcName, Prototype) \
namespace detail { \
template<typename U> \
class traitsName \
{ \
typedef std::uint8_t yes; \
typedef std::uint16_t no; \
template <typename T, T> struct type_check; \
template <typename T = U> static yes &chk(type_check<Prototype, &funcName>*); \
template <typename > static no &chk(...); \
public: \
static bool const value = sizeof(chk<U>(0)) == sizeof(yes); \
}; \
} \
template <typename U> \
struct traitsName : std::conditional<detail::traitsName<U>::value, \
std::true_type, std::false_type>::type {}
Теперь предположим, что:
unsigned int hasher(const int& item);
Теперь создайте черту:
HAS_TEMPLATED_FUNC(has_hasher, hasher, unsigned int (*)(const T&));
// some test.
static_assert(has_hasher<int>::value, "");
static_assert(!has_hasher<char>::value, "");
Теперь есть какой-то способ использовать его
Диспетчерская метка:
template <typename Item>
class foo
{
public:
void method()
{
method(has_hasher<Item>());
}
private:
void method(std::true_type)
{
// You may use hasher here.
hasher(Item{});
}
void method(std::false_type)
{
// You cannot use hasher here.
}
};
или сфина:
template <typename Item>
class foo
{
public:
template <typename T = Item>
typename std::enable_if<has_hasher<T>::value, void>::type
method()
{
// You may use hasher here.
hasher(Item{});
}
template <typename T = Item>
typename std::enable_if<!has_hasher<T>::value, void>::type
method()
{
// You cannot use hasher here.
}
};