Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.50/8: Рейтинг темы: голосов - 8, средняя оценка - 4.50
142 / 20 / 2
Регистрация: 07.01.2016
Сообщений: 230

Лямбда-функция в качестве аргумента функции

31.10.2019, 23:47. Показов 1789. Ответов 9

Студворк — интернет-сервис помощи студентам
Добрый вечер!

Как надо сделать, чтобы вот эта функция могла работать с лямбдой-функцией?:
C++
1
2
3
4
5
6
7
8
template <typename ReturnType, typename ...ArgumentTypes>
Future<ReturnType> runAsync(ReturnType (*function)(ArgumentTypes...), ArgumentTypes&&... args)
{
    auto* task = new Task<ReturnType(ArgumentTypes...)>(function, std::forward<ArgumentTypes>(args)...);
    tasks.push(task);
 
    return task->getFuture();
}
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
31.10.2019, 23:47
Ответы с готовыми решениями:

Использование лямбда выражения в качестве аргумента функции
После того как я познакомился с ламбда функциями я хотел проверить их знания на некой практике, но я столкнулся с тем, что не знаю как...

Функция в качестве аргумента другой функции по умолчанию
Здравствуйте, поясню немного заголовок. Аргумент функции по умолчанию: void function ( int a=0 ) { ... } Функция в качестве...

Передача лямбда-функции в качестве параметра
Коллеги, доброго всем времени суток. Помогите, пожалуйста, с такой проблемой. Передаю функцию в качестве параметра в другую функцию. ...

9
Неэпический
 Аватар для Croessmah
18144 / 10728 / 2066
Регистрация: 27.09.2012
Сообщений: 27,026
Записей в блоге: 1
01.11.2019, 00:43
Как-то так?
C++
1
2
3
4
5
6
7
8
template <typename T, typename ...ArgumentTypes>
auto runAsync(T function, ArgumentTypes&&... args)
{
    auto* task = new Task<T>(function, std::forward<ArgumentTypes>(args)...);
    tasks.push(task);
 
    return task->getFuture();
}
1
142 / 20 / 2
Регистрация: 07.01.2016
Сообщений: 230
01.11.2019, 13:25  [ТС]
Croessmah, я попытался так сделать, по теории должно было заработать) Но так этого и не произошло(

Вот список ошибок:
Кликните здесь для просмотра всего текста
Code
1
2
3
4
5
6
7
8
Ошибка    C3536    task: не может использоваться до инициализации TaskManager.h   42  
Ошибка    C2664    "bool boost::lockfree::queue<RE::AbstractTask *>::push(const T &)": невозможно преобразовать аргумент 1 из "int" в "const T &"
        with
        [
            T=RE::AbstractTask *
        ]   TaskManager.h   44  
Ошибка    C3313    "rValue": переменная не может иметь тип "void"    main.cpp    25  
Ошибка    C3536    rValue: не может использоваться до инициализации   main.cpp    26


И самая главная наверное тут ошибка:
Code
1
2
3
4
5
Ошибка    C2027    использование неопределенного типа "RE::Task<T>"
        with
        [
            T=int (__cdecl *)(int)
        ]   TaskManager.h   42
Похоже, он не может вывести тип, но я не понимаю, почему же так это происходит?

Вот, может быть вам поможет дать на этот вопрос ответ некоторый код:

TaskManager.h
Кликните здесь для просмотра всего текста

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#ifndef TASKMANAGER_H
#define TASKMANAGER_H
 
// STD
#include <any>
#include <atomic>
#include <memory>
#include <utility>
#include <thread>
#include <future>
#include <functional>
 
// Boost
#include <boost/utility.hpp>
#include <boost/lockfree/queue.hpp>
 
// RE
#include "Singleton.h"
#include "Task.h"
#include "Future.h"
 
namespace RE
{
    class TaskManager;
    extern TaskManager* RTaskManager;
 
    class TaskManager
    {
        RE_SINGLETON(TaskManager)
 
        TaskManager();
        ~TaskManager();
    public:
        template <typename T, typename ...ArgumentTypes>
        auto runAsync(T function, ArgumentTypes&& ... args)
        {
            auto* task = new Task<T>(function, std::forward<ArgumentTypes>(args)...);
            tasks.push(task);
 
            return task->getFuture();
        }
 
        std::string getInfo();
 
    private:
        std::vector<std::unique_ptr<std::thread>> threads;
 
        boost::lockfree::queue<AbstractTask*> tasks = boost::lockfree::queue<AbstractTask*>(0);
        std::atomic_size_t              tasksCount  = 0;
 
        std::atomic_bool isWork = false;
 
        void threadLoop();
    };
}
 
#endif //!TASKMANAGER_H


Task.h
Кликните здесь для просмотра всего текста

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#ifndef TASK_H
#define TASK_H
 
// STD
#include <thread>
#include <future>
 
// RE
#include "Utilities.h"
#include "Future.h"
 
namespace RE
{
    class AbstractTask
    {
    public:
        virtual ~AbstractTask() {}
        virtual void run() {}
    };
 
    template <typename>
    class Task; // Not defined
 
    template <typename ReturnType, typename ...ArgumentTypes>
    class Task <ReturnType(ArgumentTypes...)> : public AbstractTask
    {
        using FunctionType  = ReturnType(*)(ArgumentTypes...);
    public:
        Task(FunctionType task, ArgumentTypes... arguments)
            : task(task)
        {
            argsTuple = std::make_tuple(std::forward<ArgumentTypes>(arguments)...);
        }
 
        //RE_NONCOPYABLE(Task<T>)
        Task<ReturnType(ArgumentTypes...)>& operator=(const Task<ReturnType(ArgumentTypes...)>&)    = delete;
        Task<ReturnType(ArgumentTypes...)>& operator=(Task<ReturnType(ArgumentTypes...)>&&)         = delete;
 
        Future<ReturnType> getFuture()
        {
            return Future<ReturnType>(future);
        }
 
        void run() override
        {
            future->value   = std::apply(task, argsTuple);
            future->isReady = true;
        }
 
    private:
        FunctionType task;
        std::shared_ptr<__Future<ReturnType>> future = std::make_shared<__Future<ReturnType>>();
 
        std::tuple<ArgumentTypes...> argsTuple;
    };
}
 
#endif //!TASK_H


Future.h
Кликните здесь для просмотра всего текста

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#ifndef FUTURE_H
#define FUTURE_H
 
// STD
#include <atomic>
#include <utility>
 
// RE
#include "Utilities.h"
 
namespace RE
{
    template<typename T>
    class __Future
    {
    public:
        __Future()  {}
        ~__Future() {}
        //RE_NONCOPYABLE(__Future<T>)
        __Future<T>& operator=(const __Future&) = delete;
        __Future<T>& operator=(__Future&&)      = delete;
 
        std::atomic_bool isReady = false;
        T value;
    };
 
    template<typename T>
    class Future
    {
    public:
        Future(std::shared_ptr<__Future<T>> future_) : future_(future_)
        {
        }
 
        Future(const Future&) = delete;
        Future(Future&& future)
        {
            *this = std::move(future);
        }
 
        ~Future() {}
 
        void wait()
        {
            while (!future_->isReady) {}
        }
 
        T get()
        {
            while (!future_->isReady) {}
            return std::move(future_->value);
        }
 
        Future& operator=(const Future&) = delete;
        Future& operator=(Future&& future)
        {
            if (this == &future) {
                return *this;
            }
 
            future_ = future.future_;
            return *this;
        }
 
    private:
        std::shared_ptr<__Future<T>> future_;
    };
}
 
#endif //!FUTURE_H


main.cpp
Кликните здесь для просмотра всего текста

C++
1
2
3
4
5
6
7
8
9
10
11
int doWork(int value)
{
    return value;
}
 
int main()
{
    //...
    auto rValue = RTaskManager->runAsync(doWork, 5);
    //...
}
0
Неэпический
 Аватар для Croessmah
18144 / 10728 / 2066
Регистрация: 27.09.2012
Сообщений: 27,026
Записей в блоге: 1
01.11.2019, 13:26
Task специализирован только для указателей на функции.
1
142 / 20 / 2
Регистрация: 07.01.2016
Сообщений: 230
01.11.2019, 14:47  [ТС]
Croessmah, можете пожалуйста показать пример, чтобы класс мог принимать лямбду, и чтобы можно было получить из нее тип возращаемого значения и типы аргументов?
0
2734 / 888 / 331
Регистрация: 10.02.2018
Сообщений: 2,097
01.11.2019, 15:17
Не силён в шаблонах, мог накосячить. Как-то пробовал некие варианты с лямбдами, может найдёте что-то полезным. Общий смысл был в том, что бы обернуть передаваемую через аргументы функцию или лямбду в std::function. В коде шаблонный класс Signal, в него накидываются разные функции, в том числе лямбда. Потом весь список накиданных функций вызывается скопом.
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
//-------------------------------------------------------------------------------------------------
// функции классов, глобальные функции и лямбды в одном контейнере
//-------------------------------------------------------------------------------------------------
 
//-------------------------------------------------------------------------------------------------
#include <iostream>
#include <vector>
#include <functional>
 
//-------------------------------------------------------------------------------------------------
// шаблон
//-------------------------------------------------------------------------------------------------
template<typename resT, typename... argT>
struct Signal
{
    using funcT = std::function<resT(argT...)>;
 
    // контейнер для хранения списка
    std::vector<funcT> slots;
 
    // заполнение контейнера функциями класса
    template<class T>
    void connect(T *t, resT(T::*f)(argT... args))
    {
        slots.push_back(funcT([=](argT... args)->resT { return (t->*f)(args...); }));
    }
 
    // заполнение контейнера глобальными функциями или лямбдами
    template<class T>
    void connect(T func)
    {
        slots.push_back(funcT(func));
    }
 
    // вызов функций
    void emit(argT... args)
    {
        for (funcT &f : slots)
        {
            f(args...);
        }
    }
};
 
//-------------------------------------------------------------------------------------------------
// класс с тестовой функцией
//-------------------------------------------------------------------------------------------------
struct A
{
    void func1(int arg1, int arg2) { std::cout << "A::func(" << arg1 << "," << arg2 << ")" << std::endl; }
};
 
//-------------------------------------------------------------------------------------------------
// ещё один класс с тестовой функцией
//-------------------------------------------------------------------------------------------------
struct B
{
    void func2(int arg1, int arg2) { std::cout << "B::func(" << arg1 << "," << arg2 << ")" << std::endl; }
};
 
//-------------------------------------------------------------------------------------------------
// статичная тестовая функция
//-------------------------------------------------------------------------------------------------
void func3(int arg1, int arg2) { std::cout << "func3(" << arg1 << "," << arg2 << ")" << std::endl; }
 
//-------------------------------------------------------------------------------------------------
int main(int argc, char* argv[])
{
    // заголовок
    std::cout << "======= class7 =======" << std::endl;
 
    // экземпляры
    A a;
    B b;
 
    // контейнер для хранения списка функций
    Signal<void, int, int> sig;
 
    // заполнение контейнера
    sig.connect(&a, &A::func1);
    sig.connect(&b, &B::func2);
    sig.connect(func3);
    sig.connect([](int x, int y) { std::cout << "lambda(" << x << "," << y << ")" << std::endl; } );
 
    // вызов функций
    sig.emit(7, 8);
 
    system("pause");
    return 0;
}
 
//-------------------------------------------------------------------------------------------------
1
142 / 20 / 2
Регистрация: 07.01.2016
Сообщений: 230
02.11.2019, 17:34  [ТС]
Итак, немножко поразмыслив, и чуть не написав свой клон std::function(спасибо Ygg, что показал пример, а то я немного тупил), получил вот такой код:

TaskManager.h
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
        // ...
        // For global functions
        template <typename T, typename ...ArgumentTypes>
        auto runAsync(T function, ArgumentTypes&& ... args)
        {
            Task<T>* task = new Task<T>(function, std::forward<ArgumentTypes>(args)...);
            tasks.push(task);
 
            return task->getFuture();
        }
 
        // For methods
        
        /* Вот тут какие-то непонятные для меня должны происходить действия */
        template <typename ClassType, typename FunctionType, typename ...ArgumentTypes>
        auto runAsync(ClassType* classPtr, FunctionType function, ArgumentTypes&& ... args)
        {
            Task<FunctionType>* task = new Task<FunctionType>(classPtr, function, std::forward<ArgumentTypes>(args)...);
        /* ------------------------------------------------------------------ */
            tasks.push(task);
 
            return task->getFuture();
        }
    // ...


Task.h
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#ifndef TASK_H
#define TASK_H
 
// STD
#include <tuple>
#include <thread>
#include <future>
 
// RE
#include "Utilities.h"
#include "Future.h"
 
namespace RE
{
    class AbstractTask
    {
    public:
        virtual ~AbstractTask() {}
        virtual void run() {}
    };
 
    template <typename>
    class Task; // Not defined
 
    // No return version
    template <typename ...ArgumentTypes>
    class Task <void(ArgumentTypes...)> : public AbstractTask
    {
    public:
        using FunctionType = std::function<void(ArgumentTypes...)>;
 
        // For global functions
        template <typename T>
        Task(T&& function, ArgumentTypes&& ... arguments)
            : function(function), argsTuple(std::make_tuple(std::forward<ArgumentTypes>(arguments)...))
        {
        }
 
        // For methods
        template <typename T>
        Task(T* classPtr, void(T::*function)(ArgumentTypes...), ArgumentTypes&& ... arguments)
            : function([&](ArgumentTypes&& ... arguments) { (classPtr->*function)(std::forward<ArgumentTypes>(arguments)...); }),
                argsTuple(std::make_tuple(std::forward<ArgumentTypes>(arguments)...))
        {
        }
 
        Task<void(ArgumentTypes...)>& operator=(const Task<void(ArgumentTypes...)>&)    = delete;
        Task<void(ArgumentTypes...)>& operator=(Task<void(ArgumentTypes...)>&&)         = delete;
 
        Future<void> getFuture()
        {
            return Future<void>(future);
        }
 
        void run() override
        {
            std::apply(function, argsTuple);
            future->isReady = true;
        }
 
    private:
        FunctionType function;
        std::shared_ptr<__FutureNoReturn> future = std::make_shared<__FutureNoReturn>();
        std::tuple<ArgumentTypes...> argsTuple;
    };
 
    // Return version
    template <typename ReturnType, typename ...ArgumentTypes>
    class Task <ReturnType(ArgumentTypes...)> : public AbstractTask
    {
    public:
        using FunctionType = std::function<ReturnType(ArgumentTypes...)>;
 
        // For global functions
        template <typename T>
        Task(T&& function, ArgumentTypes&& ... arguments)
            : function(function), argsTuple(std::make_tuple(std::forward<ArgumentTypes>(arguments)...))
        {
        }
 
        // For methods
        template <typename ClassType>
        Task(ClassType* classPtr, ReturnType(ClassType::*function)(ArgumentTypes...), ArgumentTypes&& ... arguments)
            : function([&](ArgumentTypes&& ... arguments) { return (classPtr->*function)(std::forward<ArgumentTypes>(arguments)...); }),
            argsTuple(std::make_tuple(std::forward<ArgumentTypes>(arguments)...))
        {
        }
 
        Task<ReturnType(ArgumentTypes...)>& operator=(const Task<ReturnType(ArgumentTypes...)>&)    = delete;
        Task<ReturnType(ArgumentTypes...)>& operator=(Task<ReturnType(ArgumentTypes...)>&&)         = delete;
 
        Future<ReturnType> getFuture()
        {
            return Future<ReturnType>(future);
        }
 
        void run() override
        {
            future->value = std::apply(function, argsTuple);
            future->isReady = true;
        }
 
    private:
        FunctionType function;
        std::shared_ptr<__Future<ReturnType>> future = std::make_shared<__Future<ReturnType>>();
        std::tuple<ArgumentTypes...> argsTuple;
    };
}
 
#endif //!TASK_H


Future.h
Кликните здесь для просмотра всего текста

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#ifndef FUTURE_H
#define FUTURE_H
 
// STD
#include <atomic>
#include <utility>
 
// RE
#include "Utilities.h"
 
namespace RE
{
    template<typename T>
    class __AbstractFuture
    {
    public:
        __AbstractFuture& operator=(const __AbstractFuture&)    = delete;
        __AbstractFuture& operator=(__AbstractFuture&&)         = delete;
 
        std::atomic_bool isReady = false;
        virtual T getValue() = 0;
    };
 
    // Return version
    template<typename T>
    class __Future : public __AbstractFuture<T>
    {
    public:
        //RE_NONCOPYABLE(__Future<T>)
        __Future<T>& operator=(const __Future<T>&)  = delete;
        __Future<T>& operator=(__Future<T>&&)       = delete;
 
        T value;
        T getValue() override
        {
            return std::move(value);
        }
    };
 
    // No return version
    class __FutureNoReturn : public __AbstractFuture<void>
    {
    public:
        //RE_NONCOPYABLE(__Future<T>)
        __FutureNoReturn& operator=(const __FutureNoReturn&) = delete;
        __FutureNoReturn& operator=(__FutureNoReturn&&) = delete;
 
        void getValue() override
        {
        }
    };
 
    // Return version
    template<typename T>
    class Future
    {
    public:
        Future(std::shared_ptr<__Future<T>> future_) : future_(future_)
        {
        }
 
        Future(const Future&) = delete;
        Future(Future&& future)
        {
            *this = std::move(future);
        }
 
        ~Future() {}
 
        void wait()
        {
            while (!future_->isReady) {}
        }
 
        T get()
        {
            while (!future_->isReady) {}
            return std::move(future_->value);
        }
 
        Future& operator=(const Future&) = delete;
        Future& operator=(Future&& future)
        {
            if (this == &future) {
                return *this;
            }
 
            future_ = future.future_;
            return *this;
        }
 
    private:
        std::shared_ptr<__Future<T>> future_;
    };
 
    // No return version
    template<>
    class Future<void>
    {
    public:
        Future(std::shared_ptr<__FutureNoReturn> future_) : future_(future_)
        {
        }
 
        Future(const Future&) = delete;
        Future(Future&& future)
        {
            *this = std::move(future);
        }
 
        ~Future() {}
 
        void wait()
        {
            while (!future_->isReady) {}
        }
 
        void get()
        {
            while (!future_->isReady) {}
        }
 
        Future& operator=(const Future&) = delete;
        Future& operator=(Future&& future)
        {
            if (this == &future) {
                return *this;
            }
 
            future_ = future.future_;
            return *this;
        }
 
    private:
        std::shared_ptr<__FutureNoReturn> future_;
    };
}
 
#endif //!FUTURE_H


Получается, если вызывать глобальные функции или лямбды, то всё работает:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int doWork(int value)
{
    return value;
}
 
int main()
{
    // Инициализация RTaskManager
    Core::getInstance();
 
    auto task = RTaskManager->runAsync<int(int)>(doWork, 5);
    cout << task.get() << endl;
 
    return 0;
}
Но уже если подсунуть метод, то это конечто не работает.
Класс Task я сумел приспособить к методам класса:
C++
1
2
3
4
5
6
7
        // For methods
        template <typename T>
        Task(T* classPtr, void(T::*function)(ArgumentTypes...), ArgumentTypes&& ... arguments)
            : function([&](ArgumentTypes&& ... arguments) { (classPtr->*function)(std::forward<ArgumentTypes>(arguments)...); }),
                argsTuple(std::make_tuple(std::forward<ArgumentTypes>(arguments)...))
        {
        }
Но вот что нужно сделать, чтобы работала теперь вот эта функция?
C++
1
2
3
4
5
6
7
8
9
10
11
        // For methods
        /* Вот тут какие-то непонятные для меня должны происходить действия */
        template <typename ClassType, typename FunctionType, typename ...ArgumentTypes>
        auto runAsync(ClassType* classPtr, FunctionType function, ArgumentTypes&& ... args)
        {
            Task<FunctionType>* task = new Task<FunctionType>(classPtr, function, std::forward<ArgumentTypes>(args)...);
        /* ------------------------------------------------------------------ */
            tasks.push(task);
 
            return task->getFuture();
        }

И ещё один вопрос, можно ли как-нибудь сделать, чтобы не вводить каждый раз тип класса: "runAsync<function_type>(some_function);"?
0
2734 / 888 / 331
Регистрация: 10.02.2018
Сообщений: 2,097
03.11.2019, 11:29
Есть же штатная реализация для асинхронных вызовов, можно там попытаться подсмотреть идею. Если с методом класса не складывается, то его вызов можно обернуть в лямбду и использовать её для выполнения асинхронной операции, раз уж с лямбдами всё заработало.
использование штатной async
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
#include <chrono>
#include <future>
 
int main()
{
    auto lambda = [=](int arg)
    {
        std::this_thread::sleep_for(std::chrono::seconds(2));
        return arg * 2;
    };
 
    auto future = std::async(lambda, 3);
 
    std::cout << "future.get = " << future.get() << "\n";
 
    return 0;
}
1
Неэпический
 Аватар для Croessmah
18144 / 10728 / 2066
Регистрация: 27.09.2012
Сообщений: 27,026
Записей в блоге: 1
03.11.2019, 12:48
А еще есть std::packaged_task
1
142 / 20 / 2
Регистрация: 07.01.2016
Сообщений: 230
03.11.2019, 14:31  [ТС]
Итак, я пока что смог добиться решения второго вопроса, связанного с тем, чтобы не вводить аргументы:
C++
1
2
3
4
5
6
7
8
9
10
        template <typename T, typename ...ArgumentTypes>
        auto runAsync(T function, ArgumentTypes&& ... args) -> Future<typename std::result_of<T(ArgumentTypes...)>::type>
        {
            using ReturnType    = typename std::result_of<T(ArgumentTypes...)>::type;
 
            Task<ReturnType(ArgumentTypes...)>* task = new Task<ReturnType(ArgumentTypes...)>(function, std::forward<ArgumentTypes>(args)...);
            tasks.push(task);
 
            return task->getFuture();
        }
Ygg, спасибо, с лямбдами работает, если я придумаю еще вариант с указанием класса, как я хотел, то сюда выложу, может быть кому-нибудь пригодиться.

Croessmah, да, я пытался его использовать, но он мне не подошёл, потому что, во-первых, его нельзя вызывать когда ты захочешь, а только если его помещать в аргумент конструктора std::thread, то что мне не нужно было. И во-вторых, мне нужно было помещать task в контейнер, а чтобы поместить, нужно иметь класс родителя без шаблона, и вот поэтому мне пришлось заниматься велосипедостроением.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
03.11.2019, 14:31
Помогаю со студенческими работами здесь

Функция в качестве аргумента
Мне нужно написать программу, которая будет включать в себя список, который можно добавлять, проверять его заполнение, а также обрабатывать...

Перегруженная функция принимает в качестве аргумента массив
Напишите перегруженную функцию max5() для типов int и double, которая принимает в качестве аргумента массив из пяти элементов типа N и...

Функция вычисляющая значение арифметического выражения переданного в качестве аргумента
Определите функцию, которая в качестве параметра получает строку арифметического выражения. Строка содержит числа в диапазоне от 0 до 9....

Функция: максимальное из двух целых чисел, полученных в качестве аргумента
Написать функцию, которая возвращает максимальное из двух целых чисел, полученных в качестве аргумента.

Вызов родовой функции (нужно передать массив в качестве аргумента функции через указатель)
#include &lt;iostream&gt; using namespace std; template &lt;class T1&gt; class mas { public: T1 n; T1 a; void input() ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
10
Ответ Создать тему
Новые блоги и статьи
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка.
Programma_Boinc 23.12.2025
Рецензия / Мнение/ Перевод Ниже машинный перевод статьи The Thinkpad X220 Tablet is the best budget school laptop period . Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы,. . .
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru