std::bind с переменным шаблоном, связанными аргументами и заполнителями

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

У меня есть класс:

template <typename return_t,typename... args_t>
class signal_base<return_t(args_t...)>
{
    using slot_t = std::function<return_t(args_t...)>;
    using slot_id_t = std::size_t;
    /*other members...*/

    slot_id_t connect(slot_t const& slot)
    {
        slot_id_t out;
        {
            std::unique_lock<std::mutex> lk{_slots_mtx};
            _slots.emplace(_current_id,slot);
            out = _current_id++;
        }
        return out;
    }

    template<typename F, typename... a_t, std::size_t... I>
    slot_id_t attach(F&& f, a_t&&... args, index_sequence<I...> seq)
    {
        return connect(std::bind(&f,std::ref(args)..., placeholder_template<I>{}...));
    }
    template<typename F, typename... a_t>
    slot_id_t attach(F&& f, a_t&&... args)
    {
        return attach(std::forward<F&&>(f),std::forward<a_t&&>(args)..., make_index_sequence<sizeof...(args_t)>{});
    }
};

У меня появилась идея использовать последовательность заполнителей, и я использую версию C++11 index_sequence,

Я продолжаю получать ошибку компилятора:

/usr/local/include/signal_t.hpp:121:24: note: in instantiation of function template specialization 'signals::(anonymous namespace)::signal_base<void
      (const double &, int)>::attach<void (*)(example &, const double &, int), example &, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
      make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
      make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
      make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
      make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
      make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
      make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
      make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
      make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
      make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
      make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
      make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
      make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
      make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
      make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
      make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
      make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
      make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
      make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
      make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
      make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
      make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
      make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
      make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
      make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
      make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
      make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
      make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
      make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
      make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
      make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
      make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
      make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
      make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
      make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
      make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
      make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
      make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
      make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
      make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
      make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
      make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
      make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2> >' requested here
/usr/local/include/signal_t.hpp:121:24: note: (skipping 247 contexts in backtrace; use -ftemplate-backtrace-limit=0 to see all)
/usr/local/include/signal_t.hpp:121:24: note: in instantiation of function template specialization 'signals::(anonymous namespace)::signal_base<void
      (const double &, int)>::attach<void (*)(example &, const double &, int), example &, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2>,
      make_index_sequence<2> >' requested here
/usr/local/include/signal_t.hpp:121:24: note: in instantiation of function template specialization 'signals::(anonymous namespace)::signal_base<void
      (const double &, int)>::attach<void (*)(example &, const double &, int), example &, make_index_sequence<2>, make_index_sequence<2>, make_index_sequence<2> >'
      requested here
/usr/local/include/signal_t.hpp:121:24: note: in instantiation of function template specialization 'signals::(anonymous namespace)::signal_base<void
      (const double &, int)>::attach<void (*)(example &, const double &, int), example &, make_index_sequence<2>, make_index_sequence<2> >' requested here
/usr/local/include/signal_t.hpp:121:24: note: in instantiation of function template specialization 'signals::(anonymous namespace)::signal_base<void
      (const double &, int)>::attach<void (*)(example &, const double &, int), example &, make_index_sequence<2> >' requested here
main.cpp:25:9: note: in instantiation of function template specialization 'signals::(anonymous namespace)::signal_base<void (const double &, int)>::attach<void
      (*)(example &, const double &, int), example &>' requested here
    sig.attach(&example::boop,e);

Мой компайер это:

Apple LLVM version 8.0.0 (clang-800.0.42.1)

Я также пытался gcc 6.3 который просто застрял.

Мой основной:

struct example
{
    double data;

    static void boop(example& e, const double&v,int)
    {
        std::cout<<"boop";
    }
};

int main(int argc, char** argv)
{
    example e; //instance of the example
    signals::signal_t<void(const double&,int)> sig; //signal class that will call all attached listeners on emit()

    sig.attach(&example::boop,e); //attach example::boop with the first argument e, leaving the last two arguments as placeholders
    double d =0.0;
    sig.emit(d,0);//call with double and int
    return 0;
}

Я занимаюсь этим часами и не могу объяснить это. Я пробовал заменить index_sequence со стандартными версиями C++14 и не было никакой разницы.

Вот полный index_sequence а также is_placeholder Реализация, которую я использую (заимствована из поста, на который я ссылаюсь выше):

    template <size_t... Ints>
    struct index_sequence
    {
        using type = index_sequence;
        using value_type = size_t;
        static constexpr std::size_t size() noexcept { return sizeof...(Ints); }
    };

    // --------------------------------------------------------------

    template <class Sequence1, class Sequence2>
    struct _merge_and_renumber;

    template <size_t... I1, size_t... I2>
    struct _merge_and_renumber<index_sequence<I1...>, index_sequence<I2...>>
      : index_sequence<I1..., (sizeof...(I1)+I2)...>
    { };

    // --------------------------------------------------------------

    template <size_t N>
    struct make_index_sequence
      : _merge_and_renumber<typename make_index_sequence<N/2>::type,
                            typename make_index_sequence<N - N/2>::type>
    { };

    template<> struct make_index_sequence<0> : index_sequence<> { };
    template<> struct make_index_sequence<1> : index_sequence<0> { };

template<int> // begin with 0 here!
struct placeholder_template
{};

namespace std
{
    template<std::size_t N>
    struct is_placeholder< placeholder_template<N> >
        : integral_constant<std::size_t, N+1> // the one is important
    {};
}

Почему make_index_sequence кажется, расширяется так много раз, что превышает рекурсивную глубину шаблона? когда sizeof...(args_2) == 2

1 ответ

Решение

В этой функции:

template<typename F, typename... a_t, std::size_t... I>
slot_id_t attach(F&& f, a_t&&... args, index_sequence<I...> seq);

a_t является не выводимым контекстом, потому что это пакет параметров, который не является последним аргументом. В результате дедукция завершается неудачно, и ваша функция не может быть вызвана - поэтому вы просто рекурсивно вызываете себя навсегда, каждый раз добавляя один и тот же аргумент.

Вместо этого инвертируйте порядок. Положить index_sequence в качестве первого аргумента.

Другие вопросы по тегам