class A
{
public:
template<class TFn>
bool Fun(int n, TFn fn)
{
while(n --> 0)
{
if ( fn(n) )
{
return true;
}
}
return false;
}
bool Fun(int n)
{
return Fun(n, [](int n){ return true; });
}
};
int main(int argc, char* argv[])
{
A a;
a.Fun(8);
a.Fun(8, [](int n) {return n%2 == 0;});
return 0;
}
но сначала я его записал так:
class A
{
public:
template<class TFn>
bool Fun(int n, TFn fn = [](int n){ return true; }) // NB
{
while(n --> 0)
{
if ( fn(n) )
{
return true;
}
}
return false;
}
};
int main(int argc, char* argv[])
{
A a;
//a.Fun(8);// error here
a.Fun(8, [](int n) {return n%2 == 0;}); // no errorsreturn 0;
}
т.е. получается, что default параметр задать можно, но вызов с ним не возможен. Это удивительно. Оно так зачем?
PS я немного подумал и записал так:
class A
{
public:
bool Fun(int n, auto fn = [](int n){ return true; })
{
while(n --> 0)
{
if ( fn(n) )
{
return true;
}
}
return false;
}
};
int main(int argc, char* argv[])
{
A a;
//a.Fun(8);
a.Fun(8, [](int n) {return n%2 == 0;});
return 0;
}
И оно, таки, компилируется здесь ...
Хотя ошибка с вызовом a.Fun(8); осталась...
Это что-же получается? Придумали альтернативный синтаксис шаблонных функций? Это стандартизовано будет? И почему не работает вызов с default параметром?
Здравствуйте, B0FEE664, Вы писали:
BFE>Это что-же получается? Придумали альтернативный синтаксис шаблонных функций? Это стандартизовано будет? И почему не работает вызов с default параметром?
ЕМНИП, дефолтный параметр не участвует в выводе параметров шаблонной функции.
То есть
template<typename T> T f( T a = 0 ) { return T; }
// f(); // нельзя, но
f<int*>(); // можно
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали:
BFE>>Это что-же получается? Придумали альтернативный синтаксис шаблонных функций? Это стандартизовано будет? И почему не работает вызов с default параметром?
E>ЕМНИП, дефолтный параметр не участвует в выводе параметров шаблонной функции. E>То есть
template<typename T> T f( T a = 0 ) { return T; }
E>// f(); // нельзя, но
E>f<int*>(); // можно
Собственно это и не понятно — почему не участвует?
Вот в таком коде проблем нет:
template<typename T> T f( T a = 0 ) { return a; }
int main()
{
auto a = 0;
f(a);
return 0;
}
Здравствуйте, B0FEE664, Вы писали:
BFE>А в чём принципиальная разница?
В том, что нельзя написать так:
template<typename T> T f( T x = T() ) { return x; }
Я не знаю, но могу предположить, что разрешение делать этот вывод в обе стороны приводит к логическим противоречиям, а если выбирать одну, то в ту, в которую выбрали, конечно полезнее...
С другой стороны, в С++ полно логических противоречий, например, порядок вызова деструкторов static in function объектов, и ничего. Типа если нарвался на противоречие, то ССЗБ.
Но в целом я рад. Чем меньше противоречий, тем проще отлаживать сложный код...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали:
BFE>>А в чём принципиальная разница? E>В том, что нельзя написать так:
template<typename T> T f( T x = T() ) { return x; }
Как это нельзя? Можно конечно. Более того, наверняка это можно сделать формально положив, что всякая функция у которой последний параметр имеет значение по умолчанию должна добавлять в рассмотрение функцию без этого параметра и с телом, которое эквивалентно перевызову этой функции с подстановкой параметра по умолчанию.
Я бы ожидал, что для функции template<typename T> T f( T x = T() ) { return x; } должно рассматриваться две ипостаси:
template<typename T> T f( T x) { return x; }
и
template<typename T> T f()
{
return f<T>(T());
}
Так же, и для тех примеров, на которые ссылается uzhas:
template<typename T, typename U> void f(U p = T::g());
template<typename T> T f(long, int = T());
И где здесь проблема?
E>Я не знаю, но могу предположить, что разрешение делать этот вывод в обе стороны приводит к логическим противоречиям, а если выбирать одну, то в ту, в которую выбрали, конечно полезнее...
Это в какие ещё стороны?
Здравствуйте, B0FEE664, Вы писали:
BFE>Как это нельзя? Можно конечно.
В твоём варианте с auto нельзя написать аналогичный код...
E>>Я не знаю, но могу предположить, что разрешение делать этот вывод в обе стороны приводит к логическим противоречиям, а если выбирать одну, то в ту, в которую выбрали, конечно полезнее... BFE>Это в какие ещё стороны?
Использовать результаты вывода типов в выражении для параметра по умолчанию или использовать тип выражения по умолчанию в выводе типов
Я думаю, что первое ценнее, а оба сразу противоречиво.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали:
BFE>>Как это нельзя? Можно конечно. E>В твоём варианте с auto нельзя написать аналогичный код...
С аналогичным кодом для указанного примера проблемы нет:
template<typename T> T f( T x = T() ) { return x; }
аналогично:
template<typename T> T f( T x ) { return x; }
template<typename T> T f( )
{
auto x = T();
return f(x);
}
Но проблема тут в том, что код аналогичный, а не эквивалентный, так как x перестаёт быть временной переменной. Однако если подставить x прямо в вызов, то проблем нет.
E>>>Я не знаю, но могу предположить, что разрешение делать этот вывод в обе стороны приводит к логическим противоречиям, а если выбирать одну, то в ту, в которую выбрали, конечно полезнее... BFE>>Это в какие ещё стороны?
E>Использовать результаты вывода типов в выражении для параметра по умолчанию или использовать тип выражения по умолчанию в выводе типов E>Я думаю, что первое ценнее, а оба сразу противоречиво.
Если есть выражение для параметра, то рассматривать тип выражения по умолчанию не имеет смысла, так как он не используется.
Тип аргумента задаётся явно и не зависит от выражения по умолчанию, если переменная не объявлена как auto, а если переменная auto, то тип выражения по умолчанию участвует в выводе типов. Это какая-то совсем экзотика:
template<typename T> T f(auto x = T() ) { return x; }
template<typename T> T f( T x ) { return x; }
BFE>template<typename T> T f( )
BFE>{
BFE> auto x = T();
BFE> return f(x);
BFE>}
BFE>
Внутри f Т уже известен жеж, и так если написать, то вызов f() всё равно невозможен, можно только f<int>(), но это и сейчас можно...
BFE>Если есть выражение для параметра, то рассматривать тип выражения по умолчанию не имеет смысла, так как он не используется. BFE>Тип аргумента задаётся явно и не зависит от выражения по умолчанию, если переменная не объявлена как auto, а если переменная auto, то тип выражения по умолчанию участвует в выводе типов. Это какая-то совсем экзотика: BFE>
BFE>template<typename T> T f(auto x = T() ) { return x; }
BFE>
Вот тебе неэкзотика:
template<typename T> T f(T x = T() ) { return x; }
Что из чего выводить? тип T x из типа выражения T(), или тип выражения T() из типа T?
Выражения же могут быть нетривиальными, и компилятору придётся уметь решать системы логических уравнений и исследовать системы аксиом на непротиворечивость. И даже если это сделать, всё равно упрёмся в теорему Гёделя...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
E>Что из чего выводить? тип T x из типа выражения T(), или тип выражения T() из типа T?
E>Выражения же могут быть нетривиальными, и компилятору придётся уметь решать системы логических уравнений и исследовать системы аксиом на непротиворечивость. И даже если это сделать, всё равно упрёмся в теорему Гёделя...
Единственная возможная проблема, которую я вижу — это задетектить цикл или рекурсию:
template<typename T> T f(T x = T() ) { return x; }
int main()
{
auto a = f(a);
return 0;
}
Здравствуйте, B0FEE664, Вы писали:
BFE>Единственная возможная проблема, которую я вижу — это задетектить цикл или рекурсию:
функций-то может быть много... Можно сколь угодно сложную систему аксиом заенкодить...
А цикл потому и легко найти, что вывод только в одну сторону делается...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском