Как избавиться от избыточных спецификаторов типов в выражении привязки - PullRequest
3 голосов
/ 17 августа 2011

Рассмотрим следующий код:

struct f{
    void get(int a) {}
};
struct g1{
    template <typename Arg>
    void get(Arg a) {}
};
struct g2{
    template <typename... Args>
    void get(Args... args) {}
};

int f2()
{
    std::bind(&f::get,f(),2); // (A)
    std::bind(&g1::get<int>,g1(),2); // (B) redundant type specifier !
    //std::bind(&g1::get,g1(),2); // compiler error !
    std::bind(&g2::get<int, double>,g2(),2,1.1); // (C) redundant type specifiers !
    //std::bind(&g2::get,g2(),2,1.1); // compiler error !
    return 0;
}

Можно ли избавиться от избыточных параметров шаблона в случае (B) и (C)?Я ожидал бы, что std :: bind автоматически выведет типы из своих параметров.

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

Примечание: я использую gcc 4.4

Ответы [ 2 ]

3 голосов
/ 17 августа 2011

Я не думаю, что это возможно с (членами) функциями, потому что g1::get и g2::get должны быть созданы с фактическими аргументами, прежде чем их можно будет использовать.

С функциональными объектами вы можете написать функцию, которая принимает параметр шаблона шаблона, а также переменные параметры; эта функция может затем создать экземпляр шаблона объекта функции с аргументами, которые вы ему дали, и создать экземпляр по умолчанию перед привязкой параметров:

template <
    template <typename... Args> class VariadicFunc, 
    typename... ActualArgs >
auto mybind(ActualArgs... args)
    -> decltype(std::bind(VariadicFunc<ActualArgs...>(), args...))
{
    return std::bind(VariadicFunc<ActualArgs...>(), args...);
}

template <typename... Args>
struct functor
{
    void operator()(Args... args) {}
};

int main()
{
    mybind<functor>(1, 2); // instantiates a functor<int, int> and binds it
}

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

1 голос
/ 17 августа 2011

Используйте operator() вместо get метода.Это будет работать следующим образом:

#include <functional>
#include <iostream>

struct g1{
    typedef void result_type;
    template <typename Arg>
    result_type operator()(Arg a) {
        std::cout << "g1()" << std::endl;
    }
};
struct g2{
    typedef void result_type;
    template <typename... Args>
    result_type operator()(Args... args) {
        std::cout << "g2()" << std::endl;
    }
};

int main()
{
    std::bind(g1(),2)();
    std::bind(g2(),2,1.1)();
    return 0;
}

К сожалению, я не смог найти способ заставить его работать с функциями-членами.Но с реальными объектами функций это работает.

Также, к сожалению, вам нужно объявить result_type.

...