Re: Вопрос знатокам
От: B0FEE664  
Дата: 04.04.23 10:30
Оценка:
Здравствуйте, kov_serg, Вы писали:

  Скрытый текст
_>
_>// header.h
_>template<class T> void f(T);

_>//template<> void f(int);

_>inline void fi(int x) { f(x); }
_>

_>
_>#include "header.h"

_>template<> void f(int x) {}
_>

_>Почему без явного объявления f(int) имеем грабли?
_>Зачем так сделали?


// header.h
template<class T> void f(T);

//template<> void f(int);

inline void fi(int x) { f(x); }


/// @file impl_int.cpp
#include "header.h"

template<> void f(int x) {}


/// @file impl_float.cpp
#include "header.h"

template<> void f(float x) {}

void test()
{
  fi(1);
}


Которая из функций f() должна быть вызвана из функции test() ?
И каждый день — без права на ошибку...
Re[2]: Вопрос знатокам
От: night beast СССР  
Дата: 04.04.23 10:37
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>
BFE>/// @file impl_float.cpp
BFE>#include "header.h"

BFE>template<> void f(float x) {}

BFE>void test()
BFE>{
BFE>  fi(1);
BFE>}
BFE>


BFE>Которая из функций f() должна быть вызвана из функции test() ?


а как наличие или отсутствие левой специализации должно повлиять на выбор?
у тебя там не перегрузка.
Re[3]: Вопрос знатокам
От: B0FEE664  
Дата: 04.04.23 14:46
Оценка:
Здравствуйте, night beast, Вы писали:

BFE>>Которая из функций f() должна быть вызвана из функции test() ?

NB>а как наличие или отсутствие левой специализации должно повлиять на выбор?
Вот пусть kov_serg и ответит, что в таком случае должно быть.
Я рассчитываю на то, что в попытке найти ответ на этот вопрос, kov_serg поймёт зачем нужна декларация специализации перед использованием.

NB>у тебя там не перегрузка.

Компилируя файл impl_float.cpp компилятор вообще ничего не знает о template<> void f(int x) {} из файла impl_int.cpp. Вот мне и интересно, что именно, с точки зрения kov_serg, должно происходить.
И каждый день — без права на ошибку...
Re[4]: Вопрос знатокам
От: kov_serg Россия  
Дата: 04.04.23 17:57
Оценка:
Здравствуйте, B0FEE664, Вы писали:

NB>>а как наличие или отсутствие левой специализации должно повлиять на выбор?

BFE>Вот пусть kov_serg и ответит, что в таком случае должно быть.
BFE>Я рассчитываю на то, что в попытке найти ответ на этот вопрос, kov_serg поймёт зачем нужна декларация специализации перед использованием.

NB>>у тебя там не перегрузка.

BFE>Компилируя файл impl_float.cpp компилятор вообще ничего не знает о template<> void f(int x) {} из файла impl_int.cpp. Вот мне и интересно, что именно, с точки зрения kov_serg, должно происходить.
Отвечаю:
void f(int&);
void f(double&);
void f(short&);

Вот чтоб так не писать такую портянку. Хочется сказать компилятору что вот такого вида функции можно использовать но они объявлены где-то в других файлах.
template<class T>void f(T&);

Но компилятор на это смотрит через жопу иначе. Он считает что эта декларация означает что программист объявил реализацию по умолчанию, но потом.
И вот если этого потом не появилось, то возникают грабли.
Re[5]: Вопрос знатокам
От: B0FEE664  
Дата: 04.04.23 21:18
Оценка:
Здравствуйте, kov_serg, Вы писали:

_>
_>void f(int&);
_>void f(double&);
_>void f(short&);
_>

_>Вот чтоб так не писать такую портянку. Хочется сказать компилятору что вот такого вида функции можно использовать но они объявлены где-то в других файлах.
_>[cpp]

Ой, тоже мне проблема!

/// @file header.h
template<class T, class FnF>
inline void fi(T& x, FnF&& f) { f(x); }


/// @file main.cpp
#include <iostream>

void f_int(int&)
{
  std::cout << "int\n";
}

int main()
{
  int i = 0;
  fi(i, f_int);

  float x = 1.f;
  fi(x, [](float& rX) { std::cout << "float " << rX << '\n';} );

  std::cout << "the end\n";
  return 0;
}

И каждый день — без права на ошибку...
Re[6]: Вопрос знатокам
От: kov_serg Россия  
Дата: 04.04.23 21:56
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Ой, тоже мне проблема!

BFE>
BFE>/// @file header.h
BFE>template<class T, class FnF>
BFE>inline void fi(T& x, FnF&& f) { f(x); }
BFE>

BFE>
Поздравляю вы решили совершенно другую задачу.
Re[5]: Вопрос знатокам
От: rg45 СССР  
Дата: 04.04.23 21:57
Оценка:
Здравствуйте, kov_serg, Вы писали:

_>Отвечаю:

_>
_>void f(int&);
_>void f(double&);
_>void f(short&);
_>

_>Вот чтоб так не писать такую портянку. Хочется сказать компилятору что вот такого вида функции можно использовать но они объявлены где-то в других файлах.
_>
_>template<class T>void f(T&);
_>

_>Но компилятор на это смотрит через жопу иначе. Он считает что эта декларация означает что программист объявил реализацию по умолчанию, но потом.
_>И вот если этого потом не появилось, то возникают грабли.

Чтоб портянки не писать проектировать нужно нормально, по максимуму используя ADL. По-моему, только ленивый еще не писал "не специализируйте шаблоны функций".
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[6]: Вопрос знатокам
От: kov_serg Россия  
Дата: 04.04.23 22:05
Оценка:
Здравствуйте, rg45, Вы писали:

R>Чтоб портянки не писать проектировать нужно нормально, по максимуму используя ADL. По-моему, только ленивый еще не писал "не специализируйте шаблоны функций".

Без примера не понятно.
Re[7]: Вопрос знатокам
От: rg45 СССР  
Дата: 04.04.23 22:11
Оценка:
Здравствуйте, kov_serg, Вы писали:

R>>Чтоб портянки не писать проектировать нужно нормально, по максимуму используя ADL. По-моему, только ленивый еще не писал "не специализируйте шаблоны функций".


_>Без примера не понятно.


http://coliru.stacked-crooked.com/a/4b8d981c3e71c47b

#include <iostream>
#include <string>

template <typename T>
void fi(T&& t)
{
    f(t); // вообще никакого предварительного объявления не требуется
}

namespace test
{
// А типы вместе с их функциями могут располагаться в разных пространствах имен
struct A
{
    std::string name;
};

void f(const A& a)
{
   std::cout << "A: " << a.name << std::endl;
}

} // namespace test

int main()
{
    fi(test::A{"RSDN"});
}


Сразу оговорюсь, что для встроенных типов ADL таким образом не работает. Но я сильно сомневаюсь, что упомянутые выше "портянки" появляются исключительно от использования встроенных типов.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 04.04.2023 22:35 rg45 . Предыдущая версия .
Re[8]: Вопрос знатокам
От: kov_serg Россия  
Дата: 04.04.23 22:48
Оценка:
Здравствуйте, rg45, Вы писали:

R>Здравствуйте, kov_serg, Вы писали:


R>http://coliru.stacked-crooked.com/a/4b8d981c3e71c47b

Тут можно знатно огрести и потом долго отлаживать.

R>Сразу оговорюсь, что для встроенных типов ADL таким образом не работает. Но я сильно сомневаюсь, что упомянутые выше "портянки" появляются исключительно от использования встроенных типов.

Нет для базовых типов только не для всех, а для этих bool,char,unsigned char,signed char,int,unsigned int,short,unsigned short,long,unsigned long,long long,unsigned long long,float,double
для более специализированных типа std::string и хочется что бы оно искало функцию по сигнатуре. если такая объявлена то пусть использует если нет, то не собирается.

Вот что я хотел:
// header
struct A {
    template<class T>void f(T& t) { void ext_f(A*,T&); ext_f(this,t); }
};

// impl
#include <stdio.h>
#include <string>
using std::string;
void ext_f(A* self,char &v) { printf("char=%d\n",v); }
void ext_f(A* self,signed char &v) { printf("signed char=%d\n",v); }
void ext_f(A* self,unsigned char &v) { printf("unsigned char=%d\n",v); }
void ext_f(A* self,int &v)  { printf("int=%d\n",v); }
void ext_f(A* self,string &v)  { printf("string=%s\n",v.c_str()); }

int main(int argc, char const *argv[]) {
    A a[1]; char c=1; signed char cs=2; unsigned char cu=3; 
    int i=4; string s="string";
    a->f(c);
    a->f(cs);
    a->f(cu);
    a->f(i);
    a->f(s);
    return 0;
}

char=1
signed char=2
unsigned char=3
int=4
string=string
Отредактировано 04.04.2023 23:07 kov_serg . Предыдущая версия . Еще …
Отредактировано 04.04.2023 23:02 kov_serg . Предыдущая версия .
Re[9]: Вопрос знатокам
От: kov_serg Россия  
Дата: 05.04.23 11:23
Оценка:
C++ extension functions
struct A {
  template<class... T> A& f(T&...t) { void ext_f(A*,T&...); ext_f(this,t...); return *this; }
};

Всё таки C++ наркоманский язык.
Re[10]: Вопрос знатокам
От: rg45 СССР  
Дата: 05.04.23 11:55
Оценка:
Здравствуйте, kov_serg, Вы писали:

_>C++ extension functions

_>
_>struct A {
_>  template<class... T> A& f(T&...t) { void ext_f(A*,T&...); ext_f(this,t...); return *this; }
_>};
_>

_>Всё таки C++ наркоманский язык.

А объявление ext_f нафига здесь — чтоб код труднее читать было и чтоб ADL поломать?

http://coliru.stacked-crooked.com/a/7aa93214da386f99

#include <iostream>

struct A {

    template<class... T>
    A& f(T&&...t) { 
        ext_f(*this, t...);
        return *this;
    }
};

void ext_f(A&, int i)
{
    std::cout << "ext_f(A&, " << i << ")" << std::endl;
}

template <typename...T>
void ext_f(A&, T&&...t)
{
    ((std::cout << t << " "), ...);
}

int main()
{
    A a;
    a.f(42); // -> ext_f(A&, 42);
    a.f("Hello", 3.14, 'A'); // -> Hello 3.14 A
}


P.S. Обрати внимание, я специально подобрал два таких варианта исполнения ext_f, которые не укладываются в одно общее объявление (хотя бы потому, что одна функция обычная, а другая — шаблон). Тем не менее, оба эти варианта спокойно подхватываются внутри A::f.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 05.04.2023 12:49 rg45 . Предыдущая версия . Еще …
Отредактировано 05.04.2023 12:48 rg45 . Предыдущая версия .
Отредактировано 05.04.2023 11:59 rg45 . Предыдущая версия .
Re[10]: Вопрос знатокам
От: rg45 СССР  
Дата: 05.04.23 12:30
Оценка:
Здравствуйте, kov_serg, Вы писали:

_>C++ extension functions

_>
_>struct A {
_>  template<class... T> A& f(T&...t) { void ext_f(A*,T&...); ext_f(this,t...); return *this; }
_>};
_>

_>Всё таки C++ наркоманский язык.

Я думаю, что тебе интересно будет прочитать вот эту статью (если еще не читал):

http://programming-lang.com/ru/comp_programming/satter/0/j118.html

Все свободные функции, определенные в одном пространстве имен с каким-либо классом и предназначенные для выполнения каких-то действий с объектами этого класса, по факту, являются частью открытого интерфейса этого класса. Ну или расширениями — название особо сути не меняет. И это базовые принципы, без каких-либо ухищрений.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[11]: Вопрос знатокам
От: B0FEE664  
Дата: 05.04.23 12:49
Оценка: +1
Здравствуйте, rg45, Вы писали:

_>>C++ extension functions

_>>
_>>struct A {
_>>  template<class... T> A& f(T&...t) { void ext_f(A*,T&...); ext_f(this,t...); return *this; }
_>>};
_>>

_>>Всё таки C++ наркоманский язык.

R>А объявление ext_f нафига здесь — чтоб код труднее читать было и чтоб ADL поломать?


Разумным предположением может быть: чтобы по ошибке не сделать void ext_f(A*, int i), вместо void ext_f(A*, int& i)
но, "боюсь", к автору сего это не относится.
И каждый день — без права на ошибку...
Re[12]: Вопрос знатокам
От: rg45 СССР  
Дата: 05.04.23 12:53
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Разумным предположением может быть: чтобы по ошибке не сделать void ext_f(A*, int i), вместо void ext_f(A*, int& i)

BFE>но, "боюсь", к автору сего это не относится.

Ну то есть, это имеет смысл делать только в том случае, когда нужно ограничить число возможных вариантов подстановки. Причем, ограничить резко — в этом случае даже ADL уже не будет работать, а вместо этого компилятор будет искать одну конкретную функцию в текущем пространстве имен, в точности совпадающую по сигнатуре с объявленной. И я тоже думаю, что это вряд ли тот эффект, которого хочет добиться автор.

P.S. А, или даже хуже того — компилер ничего искать не будет, он просто сгенерирует вызов, соответствующий объявлению, и все, а искать эту функцию будет уже линкер.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 05.04.2023 13:19 rg45 . Предыдущая версия . Еще …
Отредактировано 05.04.2023 13:03 rg45 . Предыдущая версия .
Отредактировано 05.04.2023 13:02 rg45 . Предыдущая версия .
Отредактировано 05.04.2023 12:56 rg45 . Предыдущая версия .
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.