C++11中万能的可调用类型声明std::function<...>

本文介绍C++11中std::function模板的使用方法,它能够统一处理不同类型的可调用对象,如传统C函数、成员函数、函数对象及lambda表达式等。通过示例代码展示了如何利用std::function简化回调函数的管理。

转自: http://blog.youkuaiyun.com/smstong/article/details/44958833
在C++11中,callable object 包括传统C函数,C++成员函数,函数对象(实现了()运算符的类的实例),lambda表达式(特殊函数对象)共4种。程序设计,特别是程序库设计时,经常需要涉及到回调,如果针对每种不同的callable object单独进行声明类型,代码将会非常散乱,也不灵活。如下示例:

#include <iostream>
#include <functional>
using namespace std;

// 传统C函数
int c_function(int a, int b)
{
    return a + b;
}

// 函数对象
class Functor
{
public:
    int operator()(int a, int b)
    {
        return a + b;
    }
};

int main(int argc, char** argv)
{
    int(*f)(int, int);    // 声明函数类型,赋值只能是函数指针
    f = c_function;
    cout << f(3, 4) << endl;

    Functor ff = Functor(); // 声明函数对象类型,赋值只能是函数对象
    cout << ff(3, 4) << endl;
}

幸运的是,C++标准库的头文件里定义了std::function<>模板,此模板可以容纳所有类型的callable object.示例代码如下:

#include <iostream>
#include <functional>
using namespace std;

// 传统C函数
int c_function(int a, int b)
{
    return a + b;
}

// 函数对象
class Functor
{
public:
    int operator()(int a, int b)
    {
        return a + b;
    }
};

int main(int argc, char** argv)
{
    // 万能可调用对象类型
    std::function<int(int, int)> callableObject;

    // 可以赋值为传统C函数指针
    callableObject = c_function;
    cout << callableObject(3, 4) << endl;

    // 可以赋值为函数对象
    Functor functor;
    callableObject = functor;
    cout << callableObject(3, 4) << endl;

    // 可以赋值为lambda表达式(特殊函数对象)
    callableObject = [](int a, int b){
        return a + b;
    };
    cout << callableObject(3, 4) << endl;
}

std::function<>的这种多态能力确实很强,这样可以定义一个回调列表,而列表的元素可接受的可调用物类型并不相同。如下:

#include <iostream>
#include <functional>
#include <list>
using namespace std;

// 传统C函数
int c_function(int a, int b)
{
    return a + b;
}

// 函数对象
class Functor
{
public:
    int operator()(int a, int b)
    {
        return a + b;
    }
};

int main(int argc, char** argv)
{
    Functor functor;
    std::list<std::function<int(int, int)>> callables;

    callables.push_back(c_function);
    callables.push_back(functor);
    callables.push_back([](int x, int y)->int{
        return x + y;
    });

    for (const auto& e : callables)
    {
        cout << e(3, 4) << endl;
    }
}

对于使用C回调机制的程序库来说,C++的std::function<>能兼容传统C函数指针,所以库这一端使用std::function<>代替函数指针,并不会影响旧有客户端程序的编码方式。

In file included from main.cpp:11: solution.cpp: In member function 'int Solution::compare(std::vector<std::tuple<int, int, int, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >&, std::vector<std::tuple<int, int, int, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >&)': solution.cpp:18:33: error: no matching function for call to 'get<1>(std::vector<std::tuple<int, int, int, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >&)' if (get<1>(dataFragment1) > get<1>(dataFragmen2)) { ^ In file included from main.cpp:9: /usr/include/c++/8/utility:216:5: note: candidate: 'template<long unsigned int _Int, class _Tp1, class _Tp2> constexpr typename std::tuple_element<_Int, std::pair<_Tp1, _Tp2> >::type& std::get(std::pair<_Tp1, _Tp2>&)' get(std::pair<_Tp1, _Tp2>& __in) noexcept ^~~ /usr/include/c++/8/utility:216:5: note: template argument deduction/substitution failed: In file included from main.cpp:11: solution.cpp:18:33: note: 'std::vector<std::tuple<int, int, int, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >' is not derived from 'std::pair<_Tp1, _Tp2>' if (get<1>(dataFragment1) > get<1>(dataFragmen2)) { ^ In file included from main.cpp:9: /usr/include/c++/8/utility:221:5: note: candidate: 'template<long unsigned int _Int, class _Tp1, class _Tp2> constexpr typename std::tuple_element<_Int, std::pair<_Tp1, _Tp2> >::type&& std::get(std::pair<_Tp1, _Tp2>&&)' get(std::pair<_Tp1, _Tp2>&& __in) noexcept ^~~ /usr/include/c++/8/utility:221:5: note: template argument deduction/substitution failed: In file included from main.cpp:11: solution.cpp:18:33: note: 'std::vector<std::tuple<int, int, int, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >' is not derived from 'std::pair<_Tp1, _Tp2>' if (get<1>(dataFragment1) > get<1>(dataFragmen2)) { ^ In file included from main.cpp:9: /usr/include/c++/8/utility:226:5: note: candidate: 'template<long unsigned int _Int, class _Tp1, class _Tp2> constexpr const typename std::tuple_element<_Int, std::pair<_Tp1, _Tp2> >::type& std::get(const std::pair<_Tp1, _Tp2>&)' get(const std::pair<_Tp1, _Tp2>& __in) noexcept ^~~ /usr/include/c++/8/utility:226:5: note: template argument deduction/substitution failed: In file included from main.cpp:11: solution.cpp:18:33: note: 'std::vector<std::tuple<int, int, int, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >' is not derived from 'const std::pair<_Tp1, _Tp2>' if (get<1>(dataFragment1) > get<1>(dataFragmen2)) { ^ In file included from main.cpp:9: /usr/include/c++/8/utility:231:5: note: candidate: 'template<long unsigned int _Int, class _Tp1, class _Tp2> constexpr const typename std::tuple_element<_Int, std::pair<_Tp1, _Tp2> >::type&& std::get(const std::pair<_Tp1, _Tp2>&&)' get(const std::pair<_Tp1, _Tp2>&& __in) noexcept ^~~ /usr/include/c++/8/utility:231:5: note: template argument deduction/substitution failed: In file included from main.cpp:11: solution.cpp:18:33: note: 'std::vector<std::tuple<int, int, int, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >' is not derived from 'const std::pair<_Tp1, _Tp2>' if (get<1>(dataFragment1) > get<1>(dataFragmen2)) { ^ In file included from main.cpp:9: /usr/include/c++/8/utility:240:5: note: candidate: 'template<class _Tp, class _Up> constexpr _Tp& std::get(std::pair<_T1, _T2>&)' get(pair<_Tp, _Up>& __p) noexcept ^~~ /usr/include/c++/8/utility:240:5: note: template argument deduction/substitution failed: /usr/include/c++/8/utility:245:5: note: candidate: 'template<class _Tp, class _Up> constexpr const _Tp& std::get(const std::pair<_T1, _T2>&)' get(const pair<_Tp, _Up>& __p) noexcept ^~~ /usr/include/c++/8/utility:245:5: note: template argument deduction/substitution failed: /usr/include/c++/8/utility:250:5: note: candidate: 'template<class _Tp, class _Up> constexpr _Tp&& std::get(std::pair<_T1, _T2>&&)' get(pair<_Tp, _Up>&& __p) noexcept ^~~ /usr/include/c++/8/utility:250:5: note: template argument deduction/substitution failed: /usr/include/c++/8/utility:255:5: note: candidate: 'template<class _Tp, class _Up> constexpr const _Tp&& std::get(const std::pair<_T1, _T2>&&)' get(const pair<_Tp, _Up>&& __p) noexcept ^~~ /usr/include/c++/8/utility:255:5: note: template argument deduction/substitution failed: /usr/include/c++/8/utility:260:5: note: candidate: 'template<class _Tp, class _Up> constexpr _Tp& std::get(std::pair<_Up, _Tp>&)' get(pair<_Up, _Tp>& __p) noexcept ^~~ /usr/include/c++/8/utility:260:5: note: template argument deduction/substitution failed: /usr/include/c++/8/utility:265:5: note: candidate: 'template<class _Tp, class _Up> constexpr const _Tp& std::get(const std::pair<_Up, _Tp>&)' get(const pair<_Up, _Tp>& __p) noexcept ^~~ /usr/include/c++/8/utility:265:5: note: template argument deduction/substitution failed: /usr/include/c++/8/utility:270:5: note: candidate: 'template<class _Tp, class _Up> constexpr _Tp&& std::get(std::pair<_Up, _Tp>&&)' get(pair<_Up, _Tp>&& __p) noexcept ^~~ /usr/include/c++/8/utility:270:5: note: template argument deduction/substitution failed: /usr/include/c++/8/utility:275:5: note: candidate: 'template<class _Tp, class _Up> constexpr const _Tp&& std::get(const std::pair<_Up, _Tp>&&)' get(const pair<_Up, _Tp>&& __p) noexcept ^~~ /usr/include/c++/8/utility:275:5: note: template argument deduction/substitution failed: In file included from /usr/include/c++/8/tuple:39, from solution.cpp:8, from main.cpp:11: /usr/include/c++/8/array:307:5: note: candidate: 'template<long unsigned int _Int, class _Tp, long unsigned int _Nm> constexpr _Tp& std::get(std::array<_Tp, _Nm>&)' get(array<_Tp, _Nm>& __arr) noexcept ^~~ /usr/include/c++/8/array:307:5: note: template argument deduction/substitution failed: In file included from main.cpp:11: solution.cpp:18:33: note: 'std::vector<std::tuple<int, int, int, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >' is not derived from 'std::array<_Tp, _Nm>' if (get<1>(dataFragment1) > get<1>(dataFragmen2)) { ^ In file included from /usr/include/c++/8/tuple:39, from solution.cpp:8, from main.cpp:11: /usr/include/c++/8/array:316:5: note: candidate: 'template<long unsigned int _Int, class _Tp, long unsigned int _Nm> constexpr _Tp&& std::get(std::array<_Tp, _Nm>&&)' get(array<_Tp, _Nm>&& __arr) noexcept ^~~ /usr/include/c++/8/array:316:5: note: template argument deduction/substitution failed: In file included from main.cpp:11: solution.cpp:18:33: note: 'std::vector<std::tuple<int, int, int, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >' is not derived from 'std::array<_Tp, _Nm>' if (get<1>(dataFragment1) > get<1>(dataFragmen2)) { ^ In file included from /usr/include/c++/8/tuple:39, from solution.cpp:8, from main.cpp:11: /usr/include/c++/8/array:324:5: note: candidate: 'template<long unsigned int _Int, class _Tp, long unsigned int _Nm> constexpr const _Tp& std::get(const std::array<_Tp, _Nm>&)' get(const array<_Tp, _Nm>& __arr) noexcept ^~~ /usr/include/c++/8/array:324:5: note: template argument deduction/substitution failed: In file included from main.cpp:11: solution.cpp:18:33: note: 'std::vector<std::tuple<int, int, int, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >' is not derived from 'const std::array<_Tp, _Nm>' if (get<1>(dataFragment1) > get<1>(dataFragmen2)) { ^ In file included from /usr/include/c++/8/tuple:39, from solution.cpp:8, from main.cpp:11: /usr/include/c++/8/array:333:5: note: candidate: 'template<long unsigned int _Int, class _Tp, long unsigned int _Nm> constexpr const _Tp&& std::get(const std::array<_Tp, _Nm>&&)' get(const array<_Tp, _Nm>&& __arr) noexcept ^~~ /usr/include/c++/8/array:333:5: note: template argument deduction/substitution failed: In file included from main.cpp:11: solution.cpp:18:33: note: 'std::vector<std::tuple<int, int, int, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >' is not derived from 'const std::array<_Tp, _Nm>' if (get<1>(dataFragment1) > get<1>(dataFragmen2)) { ^ In file included from solution.cpp:8, from main.cpp:11: /usr/include/c++/8/tuple:1314:5: note: candidate: 'template<long unsigned int __i, class ... _Elements> constexpr std::__tuple_element_t<__i, std::tuple<_Elements ...> >& std::get(std::tuple<_Elements ...>&)' get(tuple<_Elements...>& __t) noexcept ^~~ /usr/include/c++/8/tuple:1314:5: note: template argument deduction/substitution failed: In file included from main.cpp:11: solution.cpp:18:33: note: 'std::vector<std::tuple<int, int, int, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >' is not derived from 'std::tuple<_Elements ...>' if (get<1>(dataFragment1) > get<1>(dataFragmen2)) { ^ In file included from solution.cpp:8, from main.cpp:11: /usr/include/c++/8/tuple:1320:5: note: candidate: 'template<long unsigned int __i, class ... _Elements> constexpr std::__tuple_element_t<__i, std::tuple<_Elements ...> >& std::get(const std::tuple<_Elements ...>&)' get(const tuple<_Elements...>& __t) noexcept ^~~ /usr/include/c++/8/tuple:1320:5: note: template argument deduction/substitution failed: In file included from main.cpp:11: solution.cpp:18:33: note: 'std::vector<std::tuple<int, int, int, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >' is not derived from 'const std::tuple<_Elements ...>' if (get<1>(dataFragment1) > get<1>(dataFragmen2)) { ^ In file included from solution.cpp:8, from main.cpp:11: /usr/include/c++/8/tuple:1326:5: note: candidate: 'template<long unsigned int __i, class ... _Elements> constexpr std::__tuple_element_t<__i, std::tuple<_Elements ...> >&& std::get(std::tuple<_Elements ...>&&)' get(tuple<_Elements...>&& __t) noexcept ^~~ /usr/include/c++/8/tuple:1326:5: note: template argument deduction/substitution failed: In file included from main.cpp:11: solution.cpp:18:33: note: 'std::vector<std::tuple<int, int, int, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >' is not derived from 'std::tuple<_Elements ...>' if (get<1>(dataFragment1) > get<1>(dataFragmen2)) { ^ In file included from solution.cpp:8, from main.cpp:11: /usr/include/c++/8/tuple:1335:5: note: candidate: 'template<long unsigned int __i, class ... _Elements> constexpr std::__tuple_element_t<__i, std::tuple<_Elements ...> >&& std::get(const std::tuple<_Elements ...>&&)' get(const tuple<_Elements...>&& __t) noexcept ^~~ /usr/include/c++/8/tuple:1335:5: note: template argument deduction/substitution failed: In file included from main.cpp:11: solution.cpp:18:33: note: 'std::vector<std::tuple<int, int, int, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >' is not derived from 'const std::tuple<_Elements ...>' if (get<1>(dataFragment1) > get<1>(dataFragmen2)) { ^ In file included from solution.cpp:8, from main.cpp:11: /usr/include/c++/8/tuple:1358:5: note: candidate: 'template<class _Tp, class ... _Types> constexpr _Tp& std::get(std::tuple<_Elements ...>&)' get(tuple<_Types...>& __t) noexcept ^~~ /usr/include/c++/8/tuple:1358:5: note: template argument deduction/substitution failed: /usr/include/c++/8/tuple:1364:5: note: candidate: 'template<class _Tp, class ... _Types> constexpr _Tp&& std::get(std::tuple<_Elements ...>&&)' get(tuple<_Types...>&& __t) noexcept ^~~ /usr/include/c++/8/tuple:1364:5: note: template argument deduction/substitution failed: /usr/include/c++/8/tuple:1370:5: note: candidate: 'template<class _Tp, class ... _Types> constexpr const _Tp& std::get(const std::tuple<_Elements ...>&)' get(const tuple<_Types...>& __t) noexcept ^~~ /usr/include/c++/8/tuple:1370:5: note: template argument deduction/substitution failed: /usr/include/c++/8/tuple:1377:5: note: candidate: 'template<class _Tp, class ... _Types> constexpr const _Tp&& std::get(const std::tuple<_Elements ...>&&)' get(const tuple<_Types...>&& __t) noexcept ^~~ /usr/include/c++/8/tuple:1377:5: note: template argument deduction/substitution failed: In file included from main.cpp:11: solution.cpp:18:56: error: no matching function for call to 'get<1>(std::vector<std::tuple<int, int, int, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >&)' if (get<1>(dataFragment1) > get<1>(dataFragmen2)) { ^ In file included from main.cpp:9: /usr/include/c++/8/utility:216:5: note: candidate: 'template<long unsigned int _Int, class _Tp1, class _Tp2> constexpr typename std::tuple_element<_Int, std::pair<_Tp1, _Tp2> >::type& std::get(std::pair<_Tp1, _Tp2>&)' get(std::pair<_Tp1, _Tp2>& __in) noexcept ^~~ /usr/include/c++/8/utility:216:5: note: template argument deduction/substitution failed: In file included from main.cpp:11: solution.cpp:18:56: note: 'std::vector<std::tuple<int, int, int, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >' is not derived from 'std::pair<_Tp1, _Tp2>' if (get<1>(dataFragment1) > get<1>(dataFragmen2)) { ^ In file included from main.cpp:9: /usr/include/c++/8/utility:221:5: note: candidate: 'template<long unsigned int _Int, class _Tp1, class _Tp2> constexpr typename std::tuple_element<_Int, std::pair<_Tp1, _Tp2> >::type&& std::get(std::pair<_Tp1, _Tp2>&&)' get(std::pair<_Tp1, _Tp2>&& __in) noexcept ^~~ /usr/include/c++/8/utility:221:5: note: template argument deduction/substitution failed: In file included from main.cpp:11: solution.cpp:18:56: note: 'std::vector<std::tuple<int, int, int, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >' is not derived from 'std::pair<_Tp1, _Tp2>' if (get<1>(dataFragment1) > get<1>(dataFragmen2)) { ^ In file included from main.cpp:9: /usr/include/c++/8/utility:226:5: note: candidate: 'template<long unsigned int _Int, class _Tp1, class _Tp2> constexpr const typename std::tuple_element<_Int, std::pair<_Tp1, _Tp2> >::type& std::get(const std::pair<_Tp1, _Tp2>&)' get(const std::pair<_Tp1, _Tp2>& __in) noexcept ^~~ /usr/include/c++/8/utility:226:5: note: template argument deduction/substitution failed: In file included from main.cpp:11: solution.cpp:18:56: note: 'std::vector<std::tuple<int, int, int, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >' is not derived from 'const std::pair<_Tp1, _Tp2>' if (get<1>(dataFragment1) > get<1>(dataFragmen2)) { ^ In file included from main.cpp:9: /usr/include/c++/8/utility:231:5: note: candidate: 'template<long unsigned int _Int, class _Tp1, class _Tp2> constexpr const typename std::tuple_element<_Int, std::pair<_Tp1, _Tp2> >::type&& std::get(const std::pair<_Tp1, _Tp2>&&)' get(const std::pair<_Tp1, _Tp2>&& __in) noexcept ^~~ /usr/include/c++/8/utility:231:5: note: template argument deduction/substitution failed: In file included from main.cpp:11: solution.cpp:18:56: note: 'std::vector<std::tuple<int, int, int, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >' is not derived from 'const std::pair<_Tp1, _Tp2>' if (get<1>(dataFragment1) > get<1>(dataFragmen2)) { ^ In file included from main.cpp:9: /usr/include/c++/8/utility:240:5: note: candidate: 'template<class _Tp, class _Up> constexpr _Tp& std::get(std::pair<_T1, _T2>&)' get(pair<_Tp, _Up>& __p) noexcept ^~~ /usr/include/c++/8/utility:240:5: note: template argument deduction/substitution failed: /usr/include/c++/8/utility:245:5: note: candidate: 'template<class _Tp, class _Up> constexpr const _Tp& std::get(const std::pair<_T1, _T2>&)' get(const pair<_Tp, _Up>& __p) noexcept ^~~ /usr/include/c++/8/utility:245:5: note: template argument deduction/substitution failed: /usr/include/c++/8/utility:250:5: note: candidate: 'template<class _Tp, class _Up> constexpr _Tp&& std::get(std::pair<_T1, _T2>&&)' get(pair<_Tp, _Up>&& __p) noexcept ^~~ /usr/include/c++/8/utility:250:5: note: template argument deduction/substitution failed: /usr/include/c++/8/utility:255:5: note: candidate: 'template<class _Tp, class _Up> constexpr const _Tp&& std::get(const std::pair<_T1, _T2>&&)' get(const pair<_Tp, _Up>&& __p) noexcept ^~~ /usr/include/c++/8/utility:255:5: note: template argument deduction/substitution failed: /usr/include/c++/8/utility:260:5: note: candidate: 'template<class _Tp, class _Up> constexpr _Tp& std::get(std::pair<_Up, _Tp>&)' get(pair<_Up, _Tp>& __p) noexcept ^~~ /usr/include/c++/8/utility:260:5: note: template argument deduction/substitution failed: /usr/include/c++/8/utility:265:5: note: candidate: 'template<class _Tp, class _Up> constexpr const _Tp& std::get(const std::pair<_Up, _Tp>&)' get(const pair<_Up, _Tp>& __p) noexcept ^~~ /usr/include/c++/8/utility:265:5: note: template argument deduction/substitution failed: /usr/include/c++/8/utility:270:5: note: candidate: 'template<class _Tp, class _Up> constexpr _Tp&& std::get(std::pair<_Up, _Tp>&&)' get(pair<_Up, _Tp>&& __p) noexcept ^~~ /usr/include/c++/8/utility:270:5: note: template argument deduction/substitution failed: /usr/include/c++/8/utility:275:5: note: candidate: 'template<class _Tp, class _Up> constexpr const _Tp&& std::get(const std::pair<_Up, _Tp>&&)' get(const pair<_Up, _Tp>&& __p) noexcept ^~~ /usr/include/c++/8/utility:275:5: note: template argument deduction/substitution failed: In file included from /usr/include/c++/8/tuple:39, from solution.cpp:8, from main.cpp:11: /usr/include/c++/8/array:307:5: note: candidate: 'template<long unsigned int _Int, class _Tp, long unsigned int _Nm> constexpr _Tp& std::get(std::array<_Tp, _Nm>&)' get(array<_Tp, _Nm>& __arr) noexcept ^~~ /usr/include/c++/8/array:307:5: note: template argument deduction/substitution failed: In file included from main.cpp:11: solution.cpp:18:56: note: 'std::vector<std::tuple<int, int, int, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >' is not derived from 'std::array<_Tp, _Nm>' if (get<1>(dataFragment1) > get<1>(dataFragmen2)) { ^ In file included from /usr/include/c++/8/tuple:39, from solution.cpp:8, from main.cpp:11: /usr/include/c++/8/array:316:5: note: candidate: 'template<long unsigned int _Int, class _Tp, long unsigned int _Nm> constexpr _Tp&& std::get(std::array<_Tp, _Nm>&&)' get(array<_Tp, _Nm>&& __arr) noexcept ^~~ /usr/include/c++/8/array:316:5: note: template argument deduction/substitution failed: In file included from main.cpp:11: solution.cpp:18:56: note: 'std::vector<std::tuple<int, int, int, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >' is not derived from 'std::array<_Tp, _Nm>' if (get<1>(dataFragment1) > get<1>(dataFragmen2)) { ^ In file included from /usr/include/c++/8/tuple:39, from solution.cpp:8, from main.cpp:11: /usr/include/c++/8/array:324:5: note: candidate: 'template<long unsigned int _Int, class _Tp, long unsigned int _Nm> constexpr const _Tp& std::get(const std::array<_Tp, _Nm>&)' get(const array<_Tp, _Nm>& __arr) noexcept ^~~ /usr/include/c++/8/array:324:5: note: template argument deduction/substitution failed: In file included from main.cpp:11: solution.cpp:18:56: note: 'std::vector<std::tuple<int, int, int, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >' is not derived from 'const std::array<_Tp, _Nm>' if (get<1>(dataFragment1) > get<1>(dataFragmen2)) { ^ In file included from /usr/include/c++/8/tuple:39, from solution.cpp:8, from main.cpp:11: /usr/include/c++/8/array:333:5: note: candidate: 'template<long unsigned int _Int, class _Tp, long unsigned int _Nm> constexpr const _Tp&& std::get(const std::array<_Tp, _Nm>&&)' get(const array<_Tp, _Nm>&& __arr) noexcept ^~~ /usr/include/c++/8/array:333:5: note: template argument deduction/substitution failed: In file included from main.cpp:11: solution.cpp:18:56: note: 'std::vector<std::tuple<int, int, int, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >' is not derived from 'const std::array<_Tp, _Nm>' if (get<1>(dataFragment1) > get<1>(dataFragmen2)) { ^ In file included from solution.cpp:8, from main.cpp:11: /usr/include/c++/8/tuple:1314:5: note: candidate: 'template<long unsigned int __i, class ... _Elements> constexpr std::__tuple_element_t<__i, std::tuple<_Elements ...> >& std::get(std::tuple<_Elements ...>&)' get(tuple<_Elements...>& __t) noexcept ^~~ /usr/include/c++/8/tuple:1314:5: note: template argument deduction/substitution failed: In file included from main.cpp:11: solution.cpp:18:56: note: 'std::vector<std::tuple<int, int, int, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >' is not derived from 'std::tuple<_Elements ...>' if (get<1>(dataFragment1) > get<1>(dataFragmen2)) { ^ In file included from solution.cpp:8, from main.cpp:11: /usr/include/c++/8/tuple:1320:5: note: candidate: 'template<long unsigned int __i, class ... _Elements> constexpr std::__tuple_element_t<__i, std::tuple<_Elements ...> >& std::get(const std::tuple<_Elements ...>&)' get(const tuple<_Elements...>& __t) noexcept ^~~ /usr/include/c++/8/tuple:1320:5: note: template argument deduction/substitution failed: In file included from main.cpp:11: solution.cpp:18:56: note: 'std::vector<std::tuple<int, int, int, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >' is not derived from 'const std::tuple<_Elements ...>' if (get<1>(dataFragment1) > get<1>(dataFragmen2)) { ^ In file included from solution.cpp:8, from main.cpp:11: /usr/include/c++/8/tuple:1326:5: note: candidate: 'template<long unsigned int __i, class ... _Elements> constexpr std::__tuple_element_t<__i, std::tuple<_Elements ...> >&& std::get(std::tuple<_Elements ...>&&)' get(tuple<_Elements...>&& __t) noexcept ^~~ /usr/include/c++/8/tuple:1326:5: note: template argument deduction/substitution failed: In file included from main.cpp:11: solution.cpp:18:56: note: 'std::vector<std::tuple<int, int, int, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >' is not derived from 'std::tuple<_Elements ...>' if (get<1>(dataFragment1) > get<1>(dataFragmen2)) { ^ In file included from solution.cpp:8, from main.cpp:11: /usr/include/c++/8/tuple:1335:5: note: candidate: 'template<long unsigned int __i, class ... _Elements> constexpr std::__tuple_element_t<__i, std::tuple<_Elements ...> >&& std::get(const std::tuple<_Elements ...>&&)' get(const tuple<_Elements...>&& __t) noexcept ^~~ /usr/include/c++/8/tuple:1335:5: note: template argument deduction/substitution failed: In file included from main.cpp:11: solution.cpp:18:56: note: 'std::vector<std::tuple<int, int, int, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >' is not derived from 'const std::tuple<_Elements ...>' if (get<1>(dataFragment1) > get<1>(dataFragmen2)) { ^ In file included from solution.cpp:8, from main.cpp:11: /usr/include/c++/8/tuple:1358:5: note: candidate: 'template<class _Tp, class ... _Types> constexpr _Tp& std::get(std::tuple<_Elements ...>&)' get(tuple<_Types...>& __t) noexcept ^~~ /usr/include/c++/8/tuple:1358:5: note: template argument deduction/substitution failed: /usr/include/c++/8/tuple:1364:5: note: candidate: 'template<class _Tp, class ... _Types> constexpr _Tp&& std::get(std::tuple<_Elements ...>&&)' get(tuple<_Types...>&& __t) noexcept ^~~ /usr/include/c++/8/tuple:1364:5: note: template argument deduction/substitution failed: /usr/include/c++/8/tuple:1370:5: note: candidate: 'template<class _Tp, class ... _Types> constexpr const _Tp& std::get(const std::tuple<_Elements ...>&)' get(const tuple<_Types...>& __t) noexcept ^~~ /usr/include/c++/8/tuple:1370:5: note: template argument deduction/substitution failed: /usr/include/c++/8/tuple:1377:5: note: candidate: 'template<class _Tp, class ... _Types> constexpr const _Tp&& std::get(const std::tuple<_Elements ...>&&)' get(const tuple<_Types...>&& __t) noexcept ^~~ /usr/include/c++/8/tuple:1377:5: note: template argument deduction/substitution failed:这是什么问题?
最新发布
07-06
C++中,`std::get` 是用于从 `std::tuple` 中提取特定索引位置的元素的模板函数。然而,在尝试对 `std::vector<std::tuple<...>>` 类型使用 `std::get<1>()` 时,会出现编译错误,因为 `std::get` 并不能直接作用于一个容器(如 `std::vector`),而只能应用于单个 `std::tuple` 对象。 ### 错误分析 错误信息 `no matching function for call to 'get<1>(std::vector<std::tuple<int, int, int, int, std::string> >&)` 表示代码试图将 `std::get<1>` 应用于整个 `std::vector` 容器,而不是具体的 `std::tuple` 元素。例如: ```cpp std::vector<std::tuple<int, int, int, int, std::string>> vec; auto value = std::get<1>(vec); // 错误:无法对 vector 使用 std::get ``` 这会导致编译失败,因为 `std::get` 的重载版本只接受 `std::tuple` 类型作为参数,而不是包含 `std::tuple` 的容器[^1]。 ### 正确用法 要正确地从 `std::vector<std::tuple<...>>` 中获取某个元组的字段,需要先访问向量中的具体元素(即 `std::tuple`),然后再调用 `std::get`。例如: ```cpp std::vector<std::tuple<int, int, int, int, std::string>> vec; vec.push_back(std::make_tuple(1, 2, 3, 4, "example")); // 正确方式:先访问 vector 中的 tuple 元素,再使用 std::get int secondElement = std::get<1>(vec[0]); ``` ### 遍历并提取字段 如果需要遍历整个 `std::vector<std::tuple<...>>` 并提取每个元组的某个字段,则可以使用循环结构: ```cpp for (const auto& item : vec) { int secondField = std::get<1>(item); // 处理 secondField } ``` ### 使用 C++17 结构化绑定简化操作 在 C++17 及以上版本中,可以通过结构化绑定来更清晰地解包元组内容: ```cpp for (const auto& [a, b, c, d, e] : vec) { // 直接使用 b 获取第二个字段 std::cout << b << std::endl; } ``` ### 总结 - **错误原因**:`std::get` 不能直接应用于 `std::vector<std::tuple<...>>`。 - **解决方法**:逐个访问 `vector` 中的 `tuple` 元素,然后对其使用 `std::get`。 - **推荐实践**:在 C++17 中使用结构化绑定以提高可读性和简洁性。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值