LINUX.ORG.RU

C++: implicit instantiation of undefined template

 


0

1

Вот такой код

https://gist.github.com/anonymous/59178dd70424666f492d

Вот такая ошибка

https://gist.github.com/anonymous/135f9da09e1fe3e11490

clang++, C++11, куда копать? Не могу понять что тут теоретически может не хватать компилятору если ему все типы нормально определили

P.S. Забыл добавить в gist заголовочные файлы

#include <iostream>
#include <vector>
#include <memory>
#include <string>
#include <functional>
#include <mutex>
#include <thread>
#include <future>
#include <deque>
#include <vector>
#include <condition_variable>
★★★★★

Последнее исправление: vertexua (всего исправлений: 1)

std::function<std::packaged_task<int ()> >

Аргументом std::function должен быть функциональный тип

std::function<void (std::packaged_task<T()>)>
Begemoth ★★★★★
()
Последнее исправление: Begemoth (всего исправлений: 1)
Ответ на: комментарий от Begemoth

Спасибо, это дейсвительно не работало. Но std::move в std::bind не могу завести все равно.

main.cc:131:33: error: no viable conversion from 'typename _Bind_helper<__is_socketlike<function<void (packaged_task<int ()>)> &>::value, function<void (packaged_task<int ()>)> &, packaged_task<int ()> >::type' (aka '_Bind<__func_type (typename decay<packaged_task<int ()> >::type)>') to 'std::function<void ()>'
        std::function<void(void)> bound_func = std::bind(unbound, std::move(task));
                                  ^            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
main.cc:148:17: note: in instantiation of function template specialization 'SimpleThreadPool::Submit<int>' requested here
    auto res = tp.Submit<int>([]()->int {
...
vertexua ★★★★★
() автор топика
Ответ на: комментарий от Begemoth

g++ дает вот такую ошибку

main.cc: In instantiation of ‘std::future<_Res> SimpleThreadPool::Submit(std::function<T()>) [with T = int]’:
main.cc:151:4:   required from here
main.cc:131:80: error: conversion from ‘std::_Bind_helper<false, std::function<void(std::packaged_task<int()>)>&, std::packaged_task<int()> >::type {aka std::_Bind<std::function<void(std::packaged_task<int()>)>(std::packaged_task<int()>)>}’ to non-scalar type ‘std::function<void()>’ requested
       std::function<void(void)> bound_func = std::bind(unbound, std::move(task));
vertexua ★★★★★
() автор топика
Ответ на: комментарий от Begemoth

Почему? Я готов переместить ее в контейнер, а потом забрать оттуда, все в одном экземпляре.

vertexua ★★★★★
() автор топика
Ответ на: комментарий от vertexua

Ты настролько Ъ?

Процитирую со stackoverflow

template<class F> function(F f);

template <class F, class A> function(allocator_arg_t, const A& a, F f);

Requires: F shall be CopyConstructible. f shall be Callable for argument types ArgTypes and return type R. The copy constructor and destructor of A shall not throw exceptions.

§20.9.11.2.1 [func.wrap.func.con]

Note that operator = is defined in terms of this constructor and swap, so the same restrictions apply:

template<class F> function& operator=(F&& f);

Effects: function(std::forward<F>(f)).swap(*this);

§20.9.11.2.1 [func.wrap.func.con]

So to answer your question: Yes, it is possible to construct a std::function from a move-capturing lambda (since this only specifies how the lambda captures), but it is not possible to construct a std::function from a move-only type (e.g. a move-capturing lambda which move-captures something that is not copy constructible).

Ключевая фраза стандарта: F shall be CopyConstructible

Begemoth ★★★★★
()
Последнее исправление: Begemoth (всего исправлений: 1)
Ответ на: комментарий от SystemD-hater

Отличная идея, но я его потом в deque не засуну, так как она определена именно для функций. Есть идеи как деку переопределить чтобы она все это добро хранила?

vertexua ★★★★★
() автор топика

Вы могли бы словами описать, что должно происходить с параметром task_func в вашем Submit()?

template <typename T> 
  std::future<T> Submit(std::function<T()> task_func) {
    std::packaged_task<T()> task;
    std::future<T> task_future = task.get_future();
    {
      std::unique_lock<std::mutex> guard_(tasks_lock_);
      std::function<std::packaged_task<T()>> unbound = [](std::packaged_task<T()> bound_task)->void {
        bound_task();
      };
      std::function<void(void)> bound_func = std::bind(unbound, std::move(task));
      tasks_.push_front(bound_func);
    }
    tasks_condvar_.notify_one();
    return task_future;
  }

А то складывается ощущение, что вам в tasks_ нужно засунуть нечто, что вызовет внутри себя task_func, а после этого взведет возвращенный из Submit-а future.

eao197 ★★★★★
()
Ответ на: комментарий от eao197

Ну собственно да. Это обычный пул потоков. Все решилось кстати простым использованием shared_ptr потому что он копируется легко. Хотя мне конечно не нужны все эти гарантии которые дает shared_ptr, но пока сойдет

vertexua ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.