Deducing function template arguments

ru.night.beast
ru.night.beast

В С++17 появилась такая вещь как Template argument deduction for class templates

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

template<typename T> void foo (Foo<T> const& x);

где Foo<T> выводится из контекста:

template<typename T>

struct Foo
{

Foo (T x) {}

};


int x;

foo(x); // что эквивалентно foo(Foo(x));

-1
рейтинг
14 комментариев
yndx-antoshkka
А это не поломает существующий код?

template <typename T>
struct Foo {
Foo (T x) {}
};

struct Bar {
operator int() const { return 0; }
};


template<typename T> void foo(Foo<T> const& x);
void foo (int x);

// ...

int main() {
Bar x;
foo(x); // was OK, now ambiguous
}
yndx-antoshkka
ru.night.beast
yndx-antoshkka, зависит от кого, как оформить.
если этот поиск вызывать только если текущие правила ничего не нашли, то не сломает.

тут попутно еще своего рода пожелание возникло.
если правильно понял текущее предложение, то там для поиска используются все конструкторы. хорошо бы иметь возможность для некоторых конструкторов исключить их из поиска (через explicit или еще каким образом)
ru.night.beast
mrgordonfreman
ru.night.beast, Если текущие правила ничего не нашли, то может лучше оставить ошибку компиляции? В спорных случаях программа скомпилируется, но будет делать совсем не то, что хотел автор.
mrgordonfreman
ru.night.beast
mrgordonfreman, это как бы логичное развитие идеи.
а так да, можно и для классов убрать (вдруг чего не то подставится)
ru.night.beast
yndx-antoshkka
> если этот поиск вызывать только если текущие правила ничего не нашли, то не сломает.

Тогда получится неконсистентно:
template<typename T> void foo (Foo<T> const& x); // #1
template<typename T> void foo (const T& x); // #2

Здесь #1 более специализированный, и логично было бы выбрать его. По текущим правилам этого не произойдёт. С вашим дополнением - тоже. Выглядит очень странно, для пользователя С++ подобное поведение будет неприятным сюрпризом.

> если правильно понял текущее предложение, то там для поиска используются все конструкторы. хорошо бы иметь возможность для некоторых конструкторов исключить их из поиска (через explicit или еще каким образом)

Эта проблема решается через SFINAE или Concepts.
yndx-antoshkka
ru.night.beast
yndx-antoshkka, при текущих правилах при передаче int выберется #2 :)
но в целом ты прав, если использовать текущие правила когда формируется общий список и среди него выбирается наиболее специализированный, то предложение не будет работать.
поэтому и предлагаю вызывать только если основной поиск отвалился (что, в том числе, позволит сохранить скорость компиляции для случаев когда предложение не используется).
это даст доп. возможности для метапрограммирования (в том числе для частичного ограничения по параметрам):
template<typename T> void foo(Foo<T, int>const & x);
template<typename T> void foo(Bar<T, double>const & x);

> Эта проблема решается через SFINAE или Concepts.

эта проблема не решается через SFINAE или Concepts поскольку конструктор ничего не знает про то, как он вызван:
template<typename T>
struct Foo{
Foo(T x);
Foo(int size);
};
Foo x(1.0); // OK
Foo y(1); // сейчас ошибка
ru.night.beast
yndx-antoshkka
Опишите подробно, формально и по шагам как вы хотите модифицировать поиск функций и определение шаблонов.

> Foo y(1); // сейчас ошибка
Эта ошибка решается через explicit deduction guides
yndx-antoshkka
ru.night.beast
yndx-antoshkka, формально вижу как-то так:
1. применить стандартный поиск.
2. если в п.1 ничего не найдено, то применить расширенный поиск.
расширенный поиск должен основываться на типах, которые не могут быть выведены из существующих параметров. для этого подготавливаем список функций, которые подходят по текущим параметрам, а для зависимых параметров пробуем применить правила ввода типов для классов. если вывод дает однозначный тип, то использовать его. если вывод дает несколько типов, то запомнить их. повторить процедуру для следующего зависимого типа. потом взять пересечение неоднозначных типов, и если оно дает единственный результат, то добавить функцию в список подходящих.
в получившемся списке подходящих функций выбрать наиболее специализированный.
как то так.

>Эта ошибка решается через explicit deduction guides
насколько понял, explicit deduction guides дополняет конструкторы, а не исключает существующие.
то есть нет, не решается :)
ru.night.beast
yndx-antoshkka
> 2.
Выглядит как куча мороки, которая мало кому поможет а всем остальным навредит.

> то есть нет, не решается :)
Пожалуйста, описывайте ваши мысли подробнее.

Один из этих deduction guide удовлетворит ваши требования?
template <class T> Foo(T) -> Foo< conditional_t<is_same_v<T, int>, double, T>>;
template <class T> Foo(T) -> Foo< enable_if_t<!is_same_v<T, int>, T>>;
yndx-antoshkka
ru.night.beast
yndx-antoshkka, добавление этих deduction guide исключит конструктор Foo(int size) из поиска и сделает использование Foo x(1) компилируемым?

сейчас список, из которого выбирается тип состоит Всех конструкторов класса + списка явный правил.
хотелось бы иметь возможность убрать конкретный конструктор из списка, в котором происходит поиск.
ru.night.beast
yndx-antoshkka
> добавление этих deduction guide исключит конструктор Foo(int size) из поиска и сделает использование Foo x(1) компилируемым?

У вас взаимоисключающие параграфы.
yndx-antoshkka
ru.night.beast
yndx-antoshkka, я описал проблему. вы предложили ее решить с помощью explicit deduction guides. у меня возник вопрос, как ее можно решить с помощью deduction guides если они никак с этим конструктором не связаны.
ru.night.beast
yndx-antoshkka
Нашёл причину возникших взаимных недопониманий.

Вашу фразу
> Foo y(1); // сейчас ошибка
я интерпретировал как "ошибка - определится неверный тип T" а не как "ошибка компиляции".

Другими словами, при вызове Foo x(1) вы хотите чтобы проинстанцировался тип Foo<int>.

Так вот, по умолчанию Foo<int> и определится, никаких ошибок компиляции не будет: open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0091r3.html
yndx-antoshkka
ru.night.beast
> Так вот, по умолчанию Foo<int> и определится, никаких ошибок компиляции не будет

это точно? тогда вопрос снимается :)
ru.night.beast
Другие идеи
Группа создана, чтобы собирать предложения к стандарту C++, организовывать их внутренние обсуждения, помогать готовить их для отправки в комитет и защищать на общих собраниях в рабочей группе по С++ Международной организации по стандартизации (ISO).