Вычет функции

Допустим, у нас есть такой шаблон класса:

template<typename F>
class A
{
public:
  template<typename... Args>
  A(F f, Args... args)
  { /* Do something... */ }
};

И теперь я хочу использовать его как-то так:

A<int(int)> a(::close, 1);

Теперь вопрос: есть ли способ опустить <int(int)>, потому что компилятор может знать эту информацию для ::close? Нет необходимости сохранять «дизайн» шаблона.

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


person Serge Roussak    schedule 06.07.2016    source источник


Ответы (3)


Нет, вы (в настоящее время) не можете. Стандартный способ сделать это — создать функцию make_like (например, make_pair< /a>, make_optional ...):

template<typename F, typename... Args>
A<std::decay_t<F>> make_A (F &&f, Args&&... args) {
    return {std::forward<F>(f), std::forward<Args>(args)...};
}

C++17 представит вывод аргументов шаблона для class, который позволит вам делать именно то, что вы хотите (см. также ответ Барри ниже).

person Holt    schedule 06.07.2016
comment
Я считаю, что правильный способ сделать эти фабричные функции — использовать std::decay или подобный трейт для A<F>. Что сделало бы это A<std::decay_t<F>>. См. en.cppreference.com/w/cpp/utility/Optional/make_Optional или другая make_* ссылка - person KABoissonneault; 06.07.2016
comment
@KABoissonneault Да, вы правы, если я использую универсальные ссылки, я должен использовать std::decay, я обновил ответ. - person Holt; 06.07.2016
comment
Не совсем понял вопрос, а значит и ответ. Вся цель состоит в том, чтобы иметь возможность сказать auto a(::close, 1)? - person Assimilater; 06.07.2016
comment
@Assimilater OP задают способ автоматического вывода параметра шаблона класса при создании экземпляра (например, A(::close, 1)), что невозможно в С++ 14. Приведенный выше ответ позволяет вам вывести параметр шаблона с помощью функции make_A, например. auto a = make_A(::close, 1) или f(make_A(::close, 1)). - person Holt; 06.07.2016
comment
Да, это формулировка OP ... может быть, формулировка меня просто сбивает с толку, потому что я мало что делал с вариативными шаблонами ... это прямое следствие только этого? Казалось, что это может применяться в более широком смысле... - person Assimilater; 06.07.2016
comment
@Assimilater Нет, это не следствие вариативных шаблонов. См. std::pair, вы не можете сделать std::pair a(1, 1) или std::pair(1, 1), потому что аргумент шаблона класса не может быть выведен, поэтому вы используете std::make_pair(1, 1) для вывода T1 и T2. - person Holt; 06.07.2016
comment
@Holt Ах, извините, что пришлось немного щелкнуть, спасибо за опыт :) - person Assimilater; 06.07.2016

Благодаря принятию вывода параметров шаблона для конструкторов в C++17 вы сможете просто написать:

A a(::close, 1);

Перед этим вам просто нужно написать фабрику, которая сделает вывод за вас:

template <class F, class... Args>
A<std::decay_t<F>> make_a(F&& f, Args&&... args) {
    return {std::forward<F>(f), std::forward<Args>(args)...};
}

auto a = make_a(::close, 1);

Это немного многословно, но, по крайней мере, вам не нужно беспокоиться об эффективности — здесь не будет копий, сделанных благодаря RVO.

person Barry    schedule 06.07.2016
comment
Re: C++17: Это так странно. Кажется, вы должны хотя бы написать A<auto> a(::close,1);. Хотя думаю привыкну. . . - person ruakh; 08.07.2016

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

template<typename F, typename... Args>
A<F> make_A(F f, Args&&... args) {
    return A<F>(f, std::forward<Args>(args)...);
}
person Benjamin Lindley    schedule 06.07.2016