Идеальная пересылка перегруженных и шаблонных функторов C ++ и их аргументов - PullRequest
0 голосов
/ 30 августа 2018

Предположим, у нас есть функция, которая выглядит следующим образом:

template <typename F, typename... A>
inline void execute(F&& functor, A&& ... args) {
    std::forward<decltype(functor)>(functor)(std::forward<decltype(args)>(args)...);
}

Это работает для простых не шаблонных функций. Тем не менее, я пытаюсь отследить шаблонную функцию (довольно надуманную):

namespace detail {

template <typename CodecImpl>
class codec
{
public:
    //
    // Encoding

    // Convenient version, returns an std::string.
    static std::string encode(const uint8_t* binary, size_t binary_size);
    static std::string encode(const char* binary, size_t binary_size);
    ...
};

class base64_rfc4648
{
public:
    template <typename Codec> using codec_impl = stream_codec<Codec, base64_rfc4648>;

    static CPPCODEC_ALWAYS_INLINE constexpr size_t alphabet_size() {
        static_assert(sizeof(base64_rfc4648_alphabet) == 64, "base64 alphabet must have 64 values");
        return sizeof(base64_rfc4648_alphabet);
    }
    static CPPCODEC_ALWAYS_INLINE constexpr char symbol(alphabet_index_t idx)
    {
        return base64_rfc4648_alphabet[idx];
    }
    ...
};

} // namespace detail

using base64_rfc4648 = detail::codec<detail::base64<detail::base64_rfc4648>>;

Попытка пересылки вышеупомянутого:

std::string buf("hello world");
execute(base64_rfc4648::encode, buf.c_str(), buf.size());

не работает. Сбой шаблона вычитается:

примечание: не удалось вывести параметр шаблона 'F'

и также отмечает:

Нет соответствующей функции для вызова 'execute(<unresolved overloaded function type>, const char*, std::__cxx11::basic_string<char>::size_type)'

Как я могу это исправить?

ПРИМЕЧАНИЕ. Я кратко изложил информацию для удобства чтения, но если потребуется дополнительная информация, я могу добавить.

Ответы [ 2 ]

0 голосов
/ 30 августа 2018

Вы можете просто использовать boost::hof, чтобы обернуть base64_rfc4648::encode в функциональный объект. execute(BOOST_HOF_LIFT(base64_rfc4648::encode), buf.c_str(), buf.size());

Вот документ BOOST_HOF_LIFT

0 голосов
/ 30 августа 2018

Я создал MCVE для работы над проблемой, а не код.

Итак, давайте предоставим универсальную функцию с именем print(), которую мы хотим отправить вашему execute()

template <typename Arg>
inline void print(Arg const & a) {
    std::cout << a << std::endl;
}

, где execute():

template <typename F, typename... A>
inline void execute(F&& functor, A&& ... args) {
    std::forward<decltype(functor)>(functor)(std::forward<decltype(args)>(args)...);
}

Когда мы пытаемся позвонить execute(print, 10), это не получается.
Проблема в том, что функция execute() не понимает, какую перегрузку из print мы пытаемся вызвать.

Теперь эту проблему можно решить двумя способами:

Первый подход, укажите полный тип шаблонной функции:

execute(print<int>, 10);

Второй подход, создать вспомогательную функцию.
Каждая проблема может быть решена добавлением еще одного слоя .
Эта вспомогательная функция поможет нам определить типы, прежде чем мы передадим ее в execute()

template <typename Arg>
inline void execute_print(Arg const & a) {
    execute(print<Arg>, a); // we need to specify which overload to be invoked
}

И тогда вы можете позвонить: execute_print(20);

Вот полный рабочий код для вашей справки (скомпилирован с использованием C ++ 11):

#include <string>
#include <iostream>

template <typename Arg>
inline void print(Arg const & a) {
    std::cout << a << std::endl;
}

template <typename F, typename... A>
inline void execute(F&& functor, A&& ... args) {
    std::forward<decltype(functor)>(functor)(std::forward<decltype(args)>(args)...);
}

template <typename Arg>
inline void execute_print(Arg const & a) {
    execute(print<Arg>, a); // we need to specify which overload to be invoked
}

int main() {
    // execute(print, 5); // wont compile
    execute(print<int>, 10);
    execute_print(20);
    return 0;
}
...