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

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

31.10.2019, 23:47. Показов 1823. Ответов 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
18149 / 10731 / 2067
Регистрация: 27.09.2012
Сообщений: 27,035
Записей в блоге: 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
18149 / 10731 / 2067
Регистрация: 27.09.2012
Сообщений: 27,035
Записей в блоге: 1
01.11.2019, 13:26
Task специализирован только для указателей на функции.
1
142 / 20 / 2
Регистрация: 07.01.2016
Сообщений: 230
01.11.2019, 14:47  [ТС]
Croessmah, можете пожалуйста показать пример, чтобы класс мог принимать лямбду, и чтобы можно было получить из нее тип возращаемого значения и типы аргументов?
0
2735 / 890 / 331
Регистрация: 10.02.2018
Сообщений: 2,111
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
2735 / 890 / 331
Регистрация: 10.02.2018
Сообщений: 2,111
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
18149 / 10731 / 2067
Регистрация: 27.09.2012
Сообщений: 27,035
Записей в блоге: 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
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий
8Observer8 02.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-collision-events-sdl3-c. zip https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11680&amp;d=1772460536 Одним из. . .
Реалии
Hrethgir 01.03.2026
Нет, я не закончил до сих пор симулятор. Эта задача сложнее. Не получилось уйти в плавсостав, но оно и к лучшему, возможно. Точнее получалось - но сварщиком в палубную команду, а это значит, в моём. . .
Ритм жизни
kumehtar 27.02.2026
Иногда приходится жить в ритме, где дел становится всё больше, а вовлечения в происходящее — всё меньше. Плотный график не даёт вниманию закрепиться ни на одном событии. Утро начинается с быстрых,. . .
SDL3 для Web (WebAssembly): Сборка библиотек: SDL3, Box2D, FreeType, SDL3_ttf, SDL3_mixer и SDL3_image из исходников с помощью CMake и Emscripten
8Observer8 27.02.2026
Недавно вышла версия 3. 4. 2 библиотеки SDL3. На странице официальной релиза доступны исходники, готовые DLL (для x86, x64, arm64), а также библиотеки для разработки под Android, MinGW и Visual Studio. . . .
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru