default λ
От: B0FEE664  
Дата: 19.05.16 17:12
Оценка:
Наткнулся на странное.

Вот простой и понятный код без проблем (?):
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 errors

    return 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 параметром?
И каждый день — без права на ошибку...
Re: default λ
От: uzhas Ниоткуда  
Дата: 19.05.16 17:19
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Вот простой


а так не проще?
http://ideone.com/nTgQpN
Re[2]: default λ
От: uzhas Ниоткуда  
Дата: 19.05.16 17:25
Оценка:
Здравствуйте, uzhas, Вы писали:

U>а так не проще?


гуглится это : http://stackoverflow.com/questions/18980781/c-function-template-using-default-parameters
про rationale не в курсе
Re[2]: default λ
От: B0FEE664  
Дата: 19.05.16 17:29
Оценка:
Здравствуйте, uzhas, Вы писали:

BFE>>Вот простой

U>а так не проще?
U>http://ideone.com/nTgQpN

Не вижу принципиальной разницы. Вопрос вот в чём: почему вызов f(); не интерпритируется как f(10); ?
И каждый день — без права на ошибку...
Re[3]: default λ
От: uzhas Ниоткуда  
Дата: 19.05.16 17:34
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Вопрос вот в чём: почему вызов f(); не интерпритируется как f(10); ?


http://stackoverflow.com/questions/9628974/why-cant-the-compiler-deduce-the-template-type-from-default-arguments
можно предположить, что это создаст проблемы при overload resolution и надо будет SFINAE усложнять
Re[4]: default λ
От: B0FEE664  
Дата: 19.05.16 17:47
Оценка:
Здравствуйте, uzhas, Вы писали:

BFE>>Вопрос вот в чём: почему вызов f(); не интерпритируется как f(10); ?

U>http://stackoverflow.com/questions/9628974/why-cant-the-compiler-deduce-the-template-type-from-default-arguments
U>можно предположить, что это создаст проблемы при overload resolution и надо будет SFINAE усложнять

Это если не лямбда. А вот для лямбды никакой проблемы быть не должно, так как каждая лямбда имеет свой уникальный тип.
И каждый день — без права на ошибку...
Re: default λ
От: Erop Россия  
Дата: 19.05.16 19:29
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Это что-же получается? Придумали альтернативный синтаксис шаблонных функций? Это стандартизовано будет? И почему не работает вызов с default параметром?


ЕМНИП, дефолтный параметр не участвует в выводе параметров шаблонной функции.
То есть
template<typename T> T f( T a = 0 ) { return T; }

// f(); // нельзя, но
f<int*>(); // можно
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[2]: default λ
От: B0FEE664  
Дата: 20.05.16 08:38
Оценка:
Здравствуйте, 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;
}


А в чём принципиальная разница?
И каждый день — без права на ошибку...
Re[5]: default λ
От: uzhas Ниоткуда  
Дата: 20.05.16 09:23
Оценка: 5 (1) +1
Здравствуйте, B0FEE664, Вы писали:


BFE>Это если не лямбда. А вот для лямбды никакой проблемы быть не должно


задачу в общем случае не осилили, поэтому и сделали запрет
я же давал ссылку, где ясно об этом сказано : http://stackoverflow.com/questions/9628974/why-cant-the-compiler-deduce-the-template-type-from-default-arguments

There would be some technical difficulties in achieving that in general.


не забываем, что в дефолтных параметрах можно указывать выражения, которые зависят от шаблонных типов

ps кстати, отвечал легендарный вандервуд https://www.linkedin.com/in/daveed-vandevoorde-7084164
Отредактировано 20.05.2016 9:34 uzhas . Предыдущая версия .
Re[3]: default λ
От: Erop Россия  
Дата: 20.05.16 09:28
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>А в чём принципиальная разница?


В том, что нельзя написать так:
template<typename T> T f( T x = T() ) { return x; }

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

С другой стороны, в С++ полно логических противоречий, например, порядок вызова деструкторов static in function объектов, и ничего. Типа если нарвался на противоречие, то ССЗБ.

Но в целом я рад. Чем меньше противоречий, тем проще отлаживать сложный код...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[6]: default λ
От: B0FEE664  
Дата: 20.05.16 09:52
Оценка: :)
Здравствуйте, uzhas, Вы писали:

BFE>>Это если не лямбда. А вот для лямбды никакой проблемы быть не должно

U>задачу в общем случае не осилили


Ладно, подождём пока осилят...
И каждый день — без права на ошибку...
Re[4]: default λ
От: B0FEE664  
Дата: 20.05.16 10:31
Оценка:
Здравствуйте, 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());

<=>
template<typename T, typename U> void f(U);
template<typename T, typename U> void f()
{
    return f<T, U>(U(T::g()));
}

template<typename T> T f(long, int);
template<typename T> T f(long l)
{
    return f<T>(l, int(T()));
}


И где здесь проблема?

E>Я не знаю, но могу предположить, что разрешение делать этот вывод в обе стороны приводит к логическим противоречиям, а если выбирать одну, то в ту, в которую выбрали, конечно полезнее...

Это в какие ещё стороны?
И каждый день — без права на ошибку...
Re[5]: default λ
От: Erop Россия  
Дата: 20.05.16 10:39
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Как это нельзя? Можно конечно.


В твоём варианте с auto нельзя написать аналогичный код...

E>>Я не знаю, но могу предположить, что разрешение делать этот вывод в обе стороны приводит к логическим противоречиям, а если выбирать одну, то в ту, в которую выбрали, конечно полезнее...

BFE>Это в какие ещё стороны?

Использовать результаты вывода типов в выражении для параметра по умолчанию или использовать тип выражения по умолчанию в выводе типов
Я думаю, что первое ценнее, а оба сразу противоречиво.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[6]: default λ
От: B0FEE664  
Дата: 20.05.16 11:07
Оценка:
Здравствуйте, 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; }
И каждый день — без права на ошибку...
Re[7]: default λ
От: Erop Россия  
Дата: 20.05.16 17:55
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>
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?
Выражения же могут быть нетривиальными, и компилятору придётся уметь решать системы логических уравнений и исследовать системы аксиом на непротиворечивость. И даже если это сделать, всё равно упрёмся в теорему Гёделя...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[8]: default λ
От: B0FEE664  
Дата: 20.05.16 18:25
Оценка:
Здравствуйте, Erop, Вы писали:

E>Вот тебе неэкзотика:
template<typename T> T f(T x = T() ) { return x; }

мы ходим по кругу
Автор: B0FEE664
Дата: 20.05.16


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;
}

И в этом нет проблемы.
И каждый день — без права на ошибку...
Re[9]: default λ
От: Erop Россия  
Дата: 20.05.16 18:37
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Единственная возможная проблема, которую я вижу — это задетектить цикл или рекурсию:


функций-то может быть много... Можно сколь угодно сложную систему аксиом заенкодить...
А цикл потому и легко найти, что вывод только в одну сторону делается...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.