LINUX.ORG.RU

Чудеса с пространствами имен в С++


0

0

Итак открываем Страуструпа и читаем раздел 7.4.2:
"Функции объявленные в разных областях видимости (не пространствах имен) не являются перегруженными."
Далее в 8.2.1 написано:
"Пространство имен является областью видимости. Обычные правила областей видимости применимы и к пространствам имен."
Отсюда насколько я понимаю следует что:
inf f() {...}
namespace test { inf f() {...} }
это не перегруженные а переопределенные функции и внутри test будет вызываться внутренняя f. Но в
namespace test1 { int f() {...} }
namespace test2 { int f() {...} }
using namespace test1;
using namespace test2;
функции f перегружены и при их вызове нужно явно разрешать неоднозначность.
Ну вроде логично. Теперь берем POSIX Threads и бубенем следующий код (Да с точки зрения работоспособности бред, но не вней фича):
#include <pthread.h>

namespace test {

int pthread_create(pthread_t* thread, const pthread_attr_t* attr, void*(*start_routine)(void*), void* arg)
{
return ::pthread_create(thread, attr, start_routine, arg);

}

int pthread_mutex_lock(pthread_mutex_t* mutex)
{
return ::pthread_mutex_lock(mutex);

}

void f()
{
pthread_t t;
pthread_mutex_t m;

pthread_create(&t, 0, 0, 0);
pthread_mutex_lock(&m);
}

}


int main(int argc, char* argv[])
{
return 0;
}
Пытаемся откомпилить как g++ test.cc и опа на:
test.cc: In function ‘void test::f()’:
test.cc:23: ошибка: вызов перегруженной функции ‘pthread_mutex_lock(pthread_mutex_t*)’ неоднозначен
test.cc:11: замечание: претенденты: int test::pthread_mutex_lock(pthread_mutex_t*)
/usr/include/pthread.h:734: замечание: int pthread_mutex_lock(pthread_mutex_t*)
Я кроме как ВАУ ничего сказать не могу - один вызов значит однозначен а второй почемуто нет. Не я все могу понять из оперы либо оба перегружены либо оба неоднозначны но такое вот я понять не могу! Может я чего непонимаю???

PS: g++ -###:
Используются внутренние спецификации.
Целевая архитектура: x86_64-suse-linux
Параметры конфигурации: ../configure --prefix=/home/kde-devel/kde --infodir=/home/kde-devel/kde/share/info --mandir=/home/kde-devel/kde/share/man --libdir=/home/kde-devel/kde/lib64 --libexecdir=/home/kde-devel/kde/lib64 --enable-languages=c,c++,objc,fortran,obj-c++,java,ada --enable-checking=release --with-gxx-include-dir=/home/kde-devel/kde/include/c++/4.4 --enable-ssp --with-slibdir=/home/kde-devel/kde/lib64 --enable-__cxa_atexit --enable-libstdcxx-allocator=new --enable-version-specific-runtime-libs --program-suffix=-4.4 --enable-linux-futex --without-system-libunwind --with-arch-32=i586 --with-tune=core2 --build=x86_64-suse-linux
Модель многопоточности: posix
gcc версия 4.4.1 20090423 (prerelease) (GCC)

Там есть что-то типа "правил Кёнига" насчет того что при поиске нужной функции анализируются неймспейсы параметров. То есть поскольку аргументом в operator<< является std::istream, то operator<< неявно импортируется из неймспейса std (что-то типа того, за точными формулировками обращайся к плюсофилам - зубрилкам). У тебя наверно сработало то что тип pthread_t принадлежит глобальному неймспейсу, и поэтому он наверно хочет взять функцию из глобального неймспейса и возникает неоднозначность.

Absurd ★★★
()
Ответ на: комментарий от Absurd

Прогнозируемый ответ. Вот вам контр аргументы:

Во-первых Страуструп п. 8.2.6 гласит что:
если функция НЕ НАЙДЕНА в КОНЕКСТЕ ЕЁ ИСПОЛЬЗОВАНИЯ, осуществляется поиск в пространстве имен её аргументов.
У нас функции в контексте использования находятся (ну или должны находиться ибо один блок блин)

Во-вторых для перегруженных операторов правила поиски имен отличаются от правил поиска имен для функций!

Втретьих для pthread_t как раз однозначно вызывается переопределенная функиция из namespace test, а для pthread_mutex_t и прочего дерьма типа rwlock и cond функции почему-то стали вдруг не переопределенными а перегруженными и вызовы неоднознычны.

Так что не катит.

mskmsk1985
() автор топика

вот именно из-за таких приколов я не использую C++

Ну его нахрен. Лучше уж Java или Ruby+модули на C быстрых операций

hellra1ser
()
Ответ на: комментарий от hellra1ser

Писк не в тему зачтен. Нечего сказать по теме лучше молчи. Это не приколы эзыка а прибамбахи компилятора скорее всего, а не используете С++ так как скорее всего просто его не знаете.

mskmsk1985
() автор топика
Ответ на: комментарий от mskmsk1985

Я сейчас иду наконец начинать выходные, но бегло пробежавшись по pthread.h заметил что декларация pthread_mutex_lock практически совпадает с твоей, а в pthread_create параметры как минимум помечены как __restrict. Макросов там туча, и для C++ pthread'сы имеют отдельные #ifdef'ы. Надо это проверить на упрощенной модели, без pthread.h.

Absurd ★★★
()
Ответ на: комментарий от mskmsk1985

я и не спорю, что C++ знаю. Я попробовал его учить, а потом понял, что ну его нахрен. Потому как со всеми языками ты решаешь задачу, а с С++ - проблемы.

hellra1ser
()
Ответ на: комментарий от mskmsk1985

> Писк не в тему зачтен. Нечего сказать по теме лучше молчи. Это не приколы эзыка а
> прибамбахи компилятора скорее всего, а не используете С++ так как скорее всего просто его не знаете.


У вас слишком хилый враппер над pthread_create. Он не принимает непримитивных типов (unions, structs, classes) из ::.

Добавьте pthread_attr_t в вызов - и вы получите свою неоднозначность. (Или возьмите реализацию с непримитивным pthread_t)

Во всём виноват поиск Кёнига как заметил предыдущий оратор.

http://rafb.net/p/oFyogE95.html

sf ★★★
()
Ответ на: комментарий от sf

-хилый враппер
+хилый вызов враппера

sf ★★★
()
Ответ на: комментарий от sf

Да тот факт, что с не примитивными типами возникае ошибка отрицать сложно. Однако, может кто откроет мне тогда глаза на жизнь как понимать ЭТО: Страуструп п. 8.2.6 гласит что: если функция НЕ НАЙДЕНА в КОНЕКСТЕ ЕЁ ИСПОЛЬЗОВАНИЯ, осуществляется поиск в пространстве имен её аргументов. Ничего про не примитивность не сказано, а извините в контектсте вызова функция объявлена с идентичными типами аргументов и если верить написанному поиска по пространству имен аргументов быть не должно. Чего я упускаю из рассуждений, что они противоречат реальной жизни?

ЗЫ: в каком смысле хилый? и почему указатль на класс вдруг не принимает указатели на класс? Вы не моглибы пояснить немного мысль? Код приведенный по ссылке не компилиркется с той же ошибкой что и мой.

mskmsk1985
() автор топика
Ответ на: комментарий от mskmsk1985

> Да тот факт, что с не примитивными типами возникае ошибка отрицать сложно. Однако,
> может кто откроет мне тогда глаза на жизнь как понимать ЭТО: Страуструп п. 8.2.6 гласит

> что: если функция НЕ НАЙДЕНА в КОНЕКСТЕ ЕЁ ИСПОЛЬЗОВАНИЯ, осуществляется поиск в

> пространстве имен её аргументов. Ничего про не примитивность не сказано, а извините в

> контектсте вызова функция объявлена с идентичными типами аргументов и если верить

> написанному поиска по пространству имен аргументов быть не должно. Чего я упускаю из

> рассуждений, что они противоречат реальной жизни?


Страуструп там очень мутно описывает приоритет, особенно в конце пункта 8.2.6 (после примера void f(Crono::Date d, std::string:: s)).

Берем стандарт ISO/IEC 14882:1998(E), Лезем в 13.3(overload resolution) -> в пункт 13.3.1.1.1 (вроде похож на наш).
> 3

> In unqualified function calls, the name is not qualified by an -> or . operator and has the more general

> form of a primary-expression. The name is looked up in the context of the function call following the nor-

> mal rules for name lookup in function calls (3.4.2). If the name resolves to a non-member function declara-

> tion, that function and its overloaded declarations constitute the set of candidate functions^116). The argu-

> ment list is the same as the expression-list in the call. ...

Пишут, что в 3.4.2 [basic.koenig.lookup] всё чэсна расписано для нашего случая (а не жуткий 3.4.1), в котором пишут, что рассматриваются _все_ функции из неймспейсов аргументов + локальный контекст.

Правильно ли, что "typedef unsigned long pthread_t;" не втягивает глобальный неймспейс - не знаю. Скорее всего - правильно, так как это не новый тип, а всего лишь алиас для примитива.

> ЗЫ: в каком смысле хилый? и почему указатль на класс вдруг не принимает указатели на

> класс? Вы не моглибы пояснить немного мысль? Код приведенный по ссылке не

> компилиркется с той же ошибкой что и мой.

В этом и был смысл приведенного примера - он самодостаточен для воспроизведения ошибки без внешних хедеров. Им можно дурить головы разработчикам помпиляторов и стандартов ;] Ошибка изменяется на более красивую (и последовательную), если вы раскомментируете передаваемый pthread_attr_t.

sf ★★★
()
Ответ на: комментарий от sf

Всегда было ощущения что в комплекте с книгой Страуструпа явно долдна поставляться чудо трава... Спасибо. Пошел штудировать стандарт...

mskmsk1985
() автор топика
Ответ на: комментарий от smh

И интель и санки дают ту же ошибку, что собсно очень логично!

mskmsk1985
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.