Я хочу, чтобы в моем коде была проверка времени компиляции, которая гарантирует, что данный класс перегружает оператор ()
, что этот оператор принимает в качестве параметров const char *
и size_t
и что его тип возврата является unsigned integer.Проверка времени компиляции функтора
Я попробовал несколько фрагментов кода, взятых из StackOverflow, но я не доволен решением я написал:
#include <type_traits>
#include <cstdint>
#include <iostream>
#include <memory>
template<class>
struct sfinae_true : std::true_type{};
namespace detail{
template<class T>
static auto test(int)
-> sfinae_true<decltype(std::declval<T>()(static_cast<const char *>(nullptr), static_cast<size_t>(0u)))>;
template<class>
static auto test(long) -> std::false_type;
} // detail::
template<class T>
struct is_functor : decltype(detail::test<T>(0)){ };
template <typename T, typename HashFn,
typename std::enable_if<std::is_unsigned<T>::value, int>::type = 0>
struct Calculation {
Calculation() {
static_assert(is_functor<HashFn>(), "BAD signature");
typedef typename std::result_of<decltype(&HashFn::operator())(HashFn, const char *, size_t)>::type return_type;
static_assert(std::is_unsigned<return_type>::value, "BAD return type");
}
T output() {
return static_cast<T>(HashFn()(nullptr, 10));
}
};
struct Hash {
uint32_t operator()(const char *buffer, size_t n) const {
return 65;
}
};
int main() {
Calculation<uint64_t, Hash> c;
c.output();
}
Извините за длиной коды, я пытался сохранить его как можно ,
Вот что мне не нравится мой код:
Если я заменяю
int
кsize_t
в списке параметров при перегрузке оператора()
, нет ошибок при компиляции, потому чтоsize_t
может быть неявно отбрасывается доint
.Если подпись неверна (например, я удаляю
const
при перегрузке оператора), первое утверждение терпит неудачу. Однако, поскольку компиляция не останавливается, я получаю три сообщения об ошибках, а на выходе компилятора несколько суматохуrty.cpp: In instantiation of ‘Calculation<T, HashFn, <anonymous> >::Calculation() [with T = long unsigned int; HashFn = Hash; typename std::enable_if<std::is_unsigned<_Tp>::value, int>::type <anonymous> = 0]’: rty.cpp:41:31: required from here rty.cpp:24:5: error: static assertion failed: BAD signature static_assert(is_functor<HashFn>(), "BAD signature"); ^ rty.cpp:25:104: error: no type named ‘type’ in ‘class std::result_of<unsigned int (Hash::*(Hash, const char*, long unsigned int))(char*, long unsigned int) const>’ typedef typename std::result_of<decltype(&HashFn::operator())(HashFn, const char *, size_t)>::type return_type; ^ rty.cpp:26:75: error: no type named ‘type’ in ‘class std::result_of<unsigned int (Hash::*(Hash, const char*, long unsigned int))(char*, long unsigned int) const>’ static_assert(std::is_unsigned<return_type>::value, "BAD return type");
Я хотел бы иметь один вызов static_assert, что-то вроде:
static_assert(is_correct_functor<HashFn>(), "BAD implementation");
Как я могу это достичь? Спасибо за вашу помощь.
Я использую C++ 11 и компиляции с г ++ 4.8
Спасибо Брайан, я сделал большой прогресс с вашим ' callable_traits'. Я замечаю, что когда я комментирую перегрузку '()' оператора '' Hash', я получаю много сообщений об ошибках. Есть ли способ улучшить выход компилятора в этом случае? – Antonin
Мне удалось найти решение. Еще раз спасибо Брайан! – Antonin
@ Антонин: можете ли вы поделиться этим решением? – Eric