Здравствуйте, night beast, Вы писали:
BFE>>Которая из функций f() должна быть вызвана из функции test() ? NB>а как наличие или отсутствие левой специализации должно повлиять на выбор?
Вот пусть kov_serg и ответит, что в таком случае должно быть.
Я рассчитываю на то, что в попытке найти ответ на этот вопрос, kov_serg поймёт зачем нужна декларация специализации перед использованием.
NB>у тебя там не перегрузка.
Компилируя файл impl_float.cpp компилятор вообще ничего не знает о template<> void f(int x) {} из файла impl_int.cpp. Вот мне и интересно, что именно, с точки зрения kov_serg, должно происходить.
Здравствуйте, 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&);
Но компилятор на это смотрит через жопу иначе. Он считает что эта декларация означает что программист объявил реализацию по умолчанию, но потом.
И вот если этого потом не появилось, то возникают грабли.
_>Вот чтоб так не писать такую портянку. Хочется сказать компилятору что вот такого вида функции можно использовать но они объявлены где-то в других файлах. _>[cpp]
_>Вот чтоб так не писать такую портянку. Хочется сказать компилятору что вот такого вида функции можно использовать но они объявлены где-то в других файлах. _>
_>template<class T>void f(T&);
_>
_>Но компилятор на это смотрит через жопу иначе. Он считает что эта декларация означает что программист объявил реализацию по умолчанию, но потом. _>И вот если этого потом не появилось, то возникают грабли.
Чтоб портянки не писать проектировать нужно нормально, по максимуму используя ADL. По-моему, только ленивый еще не писал "не специализируйте шаблоны функций".
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, rg45, Вы писали:
R>Чтоб портянки не писать проектировать нужно нормально, по максимуму используя ADL. По-моему, только ленивый еще не писал "не специализируйте шаблоны функций".
Без примера не понятно.
Здравствуйте, kov_serg, Вы писали:
R>>Чтоб портянки не писать проектировать нужно нормально, по максимуму используя ADL. По-моему, только ленивый еще не писал "не специализируйте шаблоны функций".
_>Без примера не понятно.
#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 testint main()
{
fi(test::A{"RSDN"});
}
Сразу оговорюсь, что для встроенных типов ADL таким образом не работает. Но я сильно сомневаюсь, что упомянутые выше "портянки" появляются исключительно от использования встроенных типов.
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, 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 и хочется что бы оно искало функцию по сигнатуре. если такая объявлена то пусть использует если нет, то не собирается.
#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.
--
Не можешь достичь желаемого — пожелай достигнутого.
Все свободные функции, определенные в одном пространстве имен с каким-либо классом и предназначенные для выполнения каких-то действий с объектами этого класса, по факту, являются частью открытого интерфейса этого класса. Ну или расширениями — название особо сути не меняет. И это базовые принципы, без каких-либо ухищрений.
--
Не можешь достичь желаемого — пожелай достигнутого.
_>>Всё таки C++ наркоманский язык.
R>А объявление ext_f нафига здесь — чтоб код труднее читать было и чтоб ADL поломать?
Разумным предположением может быть: чтобы по ошибке не сделать void ext_f(A*, int i), вместо void ext_f(A*, int& i)
но, "боюсь", к автору сего это не относится.
Здравствуйте, B0FEE664, Вы писали:
BFE>Разумным предположением может быть: чтобы по ошибке не сделать void ext_f(A*, int i), вместо void ext_f(A*, int& i) BFE>но, "боюсь", к автору сего это не относится.
Ну то есть, это имеет смысл делать только в том случае, когда нужно ограничить число возможных вариантов подстановки. Причем, ограничить резко — в этом случае даже ADL уже не будет работать, а вместо этого компилятор будет искать одну конкретную функцию в текущем пространстве имен, в точности совпадающую по сигнатуре с объявленной. И я тоже думаю, что это вряд ли тот эффект, которого хочет добиться автор.
P.S. А, или даже хуже того — компилер ничего искать не будет, он просто сгенерирует вызов, соответствующий объявлению, и все, а искать эту функцию будет уже линкер.
--
Не можешь достичь желаемого — пожелай достигнутого.