Когда стандарт C ++ предоставляет заголовки C, переносящие имена в глобальное пространство имен, включает ли это перегрузки?

В окончательном проекте комитета предстоящего стандарта C ++ 0x говорится:

Каждый заголовок C, каждый из которых имеет имя формы name.h, ведет себя так, как если бы каждое имя, помещенное в пространство имен стандартной библиотеки соответствующим заголовком cname, помещалось в область глобального пространства имен. Не указано, были ли эти имена сначала объявлены или определены в области видимости пространства имен (3.3.6) пространства имен std, а затем введены в глобальную область пространства имен явными объявлениями using (7.3.3).

Аналогичным образом читались и более ранние стандарты C ++.

Мой вопрос: когда заголовок C ++ #include<cname> использует перегруженные функции, все ли перегрузки вносятся #include<name.h>, поскольку перегрузки не являются отдельными «именами»?

И должно ли поведение следующего кода различаться между совместимыми со стандартами компиляторами C и C ++?

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
int main(void)
{
    double arg = -2.5;
    double result = abs(arg) / 3;
    printf("%f\n", result);
    return 0;
}

Готовые к компиляции тестовые примеры:

Судя по этому тесту, C ++ math.h действует как C, а не как C ++ cmath.

Но в Visual C ++ 2010 C ++ math.h действует как C ++ cmath.

И канарейка времени компиляции для использования с Comeau try-it-out:

#include<stdio.h>
#include<stdlib.h>
#include<math.h>

template<typename T> struct typecheck {};
template<> struct typecheck<int> { enum { value = 1 }; };

template<typename T>
typecheck<T> f(const T& t) { return typecheck<T>(); }

int main(void)
{
    double arg = -2.5;
    auto result = abs(arg) / 3;
    printf("%d\n", f(result).value);
    return 0;
}

Результат:

Comeau C/C++ 4.3.10.1 (Oct  6 2008 11:28:09) for ONLINE_EVALUATION_BETA2
Copyright 1988-2008 Comeau Computing.  All rights reserved.
MODE:strict errors C++ C++0x_extensions

"ComeauTest.c", line 15: error: class "typecheck<double>" has no member "value"
      printf("%d\n", f(result).value);
                               ^

1 error detected in the compilation of "ComeauTest.c".

Комо согласен с Visual C ++.


person Ben Voigt    schedule 10.12.2010    source источник
comment
Я не знал, что Комо поддерживает auto. Это очень полезно знать. Я думаю, вы также можете протестировать это, просто не включая <stdio.h>. <math.h> должен включать abs только в C ++, но не в C.   -  person James McNellis    schedule 10.12.2010
comment
@ Джеймс: Полагаю, вы имели в виду stdlib.h, а не stdio.h. Я столкнулся с этим при разработке примера, на ideone (gcc-4.3.4) версия C ++ только с math.h не компилировалась.   -  person Ben Voigt    schedule 10.12.2010
comment
Ах. да. Я имел в виду <stdlib.h>.   -  person James McNellis    schedule 10.12.2010


Ответы (1)


Да, все перегрузки должны быть перенесены в глобальное пространство имен. Насколько я понимаю, заголовок math.h должен выглядеть примерно так:

// math.h:
#include <cmath>

using std::abs;
// etc.

Итак, да: поведение вашей примерной программы при компиляции как программы на C отличается от поведения при компиляции как программы на C ++. Как программа на C ++, она будет вызывать std::abs(double) из <math.h>. Как программа C она будет вызывать abs(int) из <stdlib.h> (это единственная функция abs в стандартной библиотеке C, поскольку C не поддерживает перегрузку функций).

person James McNellis    schedule 10.12.2010
comment
Но abs в C не принимает аргумент double, так что вы действительно говорите, что поведение будет другим? - person Ben Voigt; 10.12.2010
comment
@Ben: Мои извинения; Я совершенно неправильно понял твой вопрос. Да, поведение было бы другим. - person James McNellis; 10.12.2010
comment
@ Джеймс: Значит, это ошибка в gcc? - person Ben Voigt; 10.12.2010
comment
@Ben Я не очень внимательно прочитал вопрос, но я бы доверял Comeau за соблюдение Стандарта C ++ перед любым другим компилятором. - person Karl Knechtel; 10.12.2010
comment
@Karl: Я тоже, поэтому я разработал тест во время компиляции, потому что бесплатное онлайн-коммюнике только компилируется, нет возможности связать или выполнить. На самом деле вопрос заключается не в том, разрешено ли внесение перегрузок (Comeau делает это, так что, конечно же, как разрешено), а в том, требуется ли это. - person Ben Voigt; 10.12.2010
comment
Я предполагаю, что да, gcc ошибается. Однако это область, где многие реализации не соответствуют требованиям. Одна из проблем заключается в том, что многие платформы напрямую используют фактические заголовки стандартной библиотеки C, и в этом случае вы не можете добиться поведения, указанного в цитируемом абзаце. Кроме того, вы не можете добиться правильного поведения от заголовков cname, потому что в конечном итоге они должны включать заголовки name.h и помещать using ::name в блок namespace std { }, поэтому имена заканчиваются как в пространстве имен std, так и в глобальном пространстве имен. Для этого были внесены некоторые изменения в стандарт C ++ 0x, хотя я - person James McNellis; 10.12.2010
comment
я не совсем уверен, что это были за изменения, и у меня нет Acrobat, установленного на этом новом ноутбуке, чтобы узнать об этом прямо сейчас :( - person James McNellis; 10.12.2010
comment
@James: Следующий абзац, следующий за тем, который я процитировал, представляет собой соответствующее примечание: [Пример: заголовок ‹cstdlib›, несомненно, предоставляет свои объявления и определения в пространстве имен std. Он также может предоставлять эти имена в глобальном пространстве имен. Заголовок ‹stdlib.h› несомненно предоставляет те же объявления и определения в глобальном пространстве имен, как и в стандарте C. Он также может предоставлять эти имена в пространстве имен std. - конец примера] - person Ben Voigt; 10.12.2010
comment
@James: Кстати, я начал предпочитать PDF-XChange Viewer для всех моих потребностей в просмотре PDF (при условии, что платформа Windows), он запускается намного быстрее, использует меньше памяти и не зависает в моем браузере, как это делает Acrobat Reader. - person Ben Voigt; 10.12.2010
comment
@James хм, я так понимаю, версии cname добавляют что-то к версиям name.h. Цитируемая часть стандарта требует (вместо того, чтобы просто принимать) версии name.h, чтобы также иметь эти дополнительные перегрузки и тому подобное. Для меня это звучит странно. - person Johannes Schaub - litb; 10.12.2010
comment
@Ben: Я думаю, что это новость в C ++ 0x. Я недавно использовал Foxit для чтения PDF, но я проверю PDF-XChange; спасибо за рекомендацию. - person James McNellis; 10.12.2010
comment
@James: [headers] из FCD: За исключением случаев, указанных в разделах 18-30 и Приложении D, содержимое каждого заголовка cname должно быть таким же, как и содержимое соответствующего заголовка name.h, как указано в стандартной библиотеке C или в C Unicode Т.Р., соответственно, как бы включением. Однако в стандартной библиотеке C ++ объявления (за исключением имен, которые определены как макросы в C) находятся в области пространства имен пространства имен std. Не указано, объявляются ли эти имена сначала в области глобального пространства имен, а затем вводятся в пространство имен std явными объявлениями-использованием. - person Ben Voigt; 10.12.2010
comment
Но я думаю, что ошибался. Формулировка явно требует, чтобы версии name.h содержали перегрузки C ++. - person Johannes Schaub - litb; 10.12.2010
comment
@Johannes: Я тоже об этом думаю. Как указано в цитате, цитируемой в OP, вы не можете использовать фактические заголовки стандартной библиотеки C в реализации стандартной библиотеки C ++; у вас должен быть отдельный набор заголовков с перегрузками C ++ в них. Я думал, что предполагалось, что вы можете использовать заголовки стандартной библиотеки C напрямую, но, возможно, я ошибался. LWG Дефект 456 - единственный известный мне недостаток по этому поводу, и он не обсуждает этот конкретный аспект проблемы. - person James McNellis; 10.12.2010
comment
@Ben: Этот язык является новым в C ++ 0x; резолюцией он был изменен на LWG Defect 456. - person James McNellis; 10.12.2010