完美转发 C++ 重载和模板化仿函数及其参数
Perfect forwarding of C++ overloaded and templated functors and its arguments
假设我们有一个如下所示的函数:
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());
无效。模板推导失败:
note: couldn't deduce template parameter 'F'
它还指出:
No matching function for call to 'execute(<unresolved overloaded function type>, const char*, std::__cxx11::basic_string<char>::size_type)'
我该如何解决这个问题?
注意:为了便于阅读,我在上面保留了简短的信息,但如果需要更多信息,我可以添加。
我创建了一个 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
的哪个 overload。
现在这个问题可以通过两种方式解决:
第一种方法,指定模板函数的完整类型:
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;
}
您可以简单地使用 boost::hof
将 base64_rfc4648::encode
包装在一个函数对象中。
execute(BOOST_HOF_LIFT(base64_rfc4648::encode), buf.c_str(), buf.size());
的文档
假设我们有一个如下所示的函数:
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());
无效。模板推导失败:
note: couldn't deduce template parameter 'F'
它还指出:
No matching function for call to
'execute(<unresolved overloaded function type>, const char*, std::__cxx11::basic_string<char>::size_type)'
我该如何解决这个问题?
注意:为了便于阅读,我在上面保留了简短的信息,但如果需要更多信息,我可以添加。
我创建了一个 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
的哪个 overload。
现在这个问题可以通过两种方式解决:
第一种方法,指定模板函数的完整类型:
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;
}
您可以简单地使用 boost::hof
将 base64_rfc4648::encode
包装在一个函数对象中。
execute(BOOST_HOF_LIFT(base64_rfc4648::encode), buf.c_str(), buf.size());