可变参数模板和标准::函数
variadic template and std::function
在下面的代码中:
#include <functional>
#include <iostream>
#include <tuple>
template <typename... t>
class a {
public:
explicit a(std::function<std::tuple<t...>()>&& p_d,
std::function<bool(t...)>&& p_f)
: m_d(std::move(p_d)), m_f(std::move(p_f)) {}
bool operator()() { return m_f(m_d()); }
private:
std::function<std::tuple<t...>()> m_d;
std::function<bool(t...)> m_f;
};
class d {
std::tuple<int, float, std::string&&> operator()() {
return std::tuple<int, float, std::string&&>(-9, 3.14, "olá!");
}
};
class f {
bool operator()(int p_i, float p_f, std::string&& p_s) {
std::cout << "i = " << p_i << ", f = " << p_f << ", s = " << p_s
<< std::endl;
return true;
}
};
int main() {
d _d;
f _f;
typedef a<int, float, std::string&&> a_t;
a_t _a(std::move(_d), std::move(_f));
_a();
return 0;
}
我收到编译器错误:
../untitled014/main.cpp: In function ‘int main()’:
../untitled014/main.cpp:38:38: error: no matching function for call to ‘a<int, float, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&>::a(std::remove_reference<d&>::type, std::remove_reference<f&>::type)’
a_t _a(std::move(_d), std::move(_f));
^
../untitled014/main.cpp:8:12: note: candidate: a<t>::a(std::function<std::tuple<_Elements ...>()>&&, std::function<bool(t ...)>&&) [with t = {int, float, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&}]
explicit a(std::function<std::tuple<t...>()>&& p_d,
^
../untitled014/main.cpp:8:12: note: no known conversion for argument 1 from ‘std::remove_reference<d&>::type {aka d}’ to ‘std::function<std::tuple<int, float, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&>()>&&’
我不明白为什么编译器找不到合适的转换,因为它在错误的最后一行中报告。
我在 Xubuntu 盒子上使用带有标志 '-std=c++14' 的 g++,并且"g++ --version" 报告 'g++ (Ubuntu 5.4.0-6ubuntu1~16.04.10( 5.4.0 20160609'
谁能告诉我我做错了什么?
谢谢!!
我在您的代码中看到至少三个错误。
没有特别的顺序...
(1(如果你想要一个功能,operator()
必须是public
的;你让它们都private
class d { // default for a class is private, so operator() is private
std::tuple<int, float, std::string&&> operator()() {
return std::tuple<int, float, std::string&&>(-9, 3.14, "olá!");
}
};
class f { // default per a class is private, so operator() is private
bool operator()(int p_i, float p_f, std::string&& p_s) {
std::cout << "i = " << p_i << ", f = " << p_f << ", s = " << p_s
<< std::endl;
return true;
}
};
你可以解决这个问题,使operator()
public
,或者更简单地说,使d
和f
struct
s。
(2("olá!"
不是初始化std::string &&
的有效值
std::tuple<int, float, std::string&&>(-9, 3.14, "olá!");
你可以编译
std::tuple<int, float, std::string&&>(-9, 3.14, std::string{"olá!"});
但这是错误的想法,因为通过这种方式,您可以使用对紧随其后销毁的对象的引用来初始化对象,并在元组内获得一个悬空引用。
我不清楚为什么要在元组中使用std::string &&
,但我怀疑您可以使用std::string
,而不是对它的引用。在您的所有代码中,非仅在此函数中。
在这种情况下,以下代码
std::tuple<int, float, std::string>(-9, 3.14, "olá!");
工程。
如果确实想要对元组中std::string
的引用,则必须传递对对象的引用,该对象的生存期足以覆盖元组的生存期。
(3(d
的operator()
返回一个std::tuple<int, float, std::string&&>
,其中f
的operator()
接受三个参数:int
、float
和std::string&&
。
因此,您不能简单地将返回的值从第一个传递到第二个,而不解压缩std::tuple
是某种方式,就像您在a::operator()
中所做的那样
bool operator()() { return m_f(m_d()); }
// ........................^^^^^^^^^^ Wrong!
您使用的是 C++14,因此无法使用std::apply()
(从 C++17 开始提供(
bool operator()() { return std::apply(m_f, m_d()); }
// ........................^^^^^^^^^^^^^^^^^^^^^^ Starting from C++17
所以你必须以某种方式模仿(std::make_index_sequence
、std::index_sequence
、std::get()
等(。
通过示例
bool operator() ()
{ return call(std::make_index_sequence<sizeof...(t)>{}); }
template <std::size_t ... Is>
auto call (std::index_sequence<Is...> const &)
{
auto tmp { m_d() }; // so m_d() is called only one time
return m_f(static_cast<t>(std::get<Is>(tmp))...);
}
call()
可以private
的位置
- 编译器如何在使用SFINAE的函数和标准函数之间确定两者是否可行
- 如何使用模板化标准::函数作为参数?
- 是否有任何 C 标准函数将值"1"传递给所有 (%s)
- 可变参数模板和标准::函数
- 是否有一个标准函数可以打印/监视stdin文件的内容,同时将数据留在stdin中
- 我怎样才能把这个标准::函数传递给标准::异步
- 如何使用标准::函数使用可变参数模板
- "AfxIsValidAddress"函数的等效标准函数是什么?
- 使用多个参数将成员功能指针转换为标准C函数
- C++:将标准::函数转换为gsl_function
- 标准::函数的 typename 关键字
- 将成员函数作为标准函数回调
- C++在全局命名空间中找不到非标准 C 函数
- 标准函数的函数指针和成员函数指针的规则是什么
- 如何使用数组创建标准::函数
- 如何在 Visual Studio 中测试时重写标准C++函数
- 在C++中使用标准 C 函数时,是否需要"std::"前缀?
- 链接器如何查找标准函数和WinAPI函数
- 标准::函数复制参数
- 互斥与标准函数调用