Dlaczego moje logowanie jest w przestrzeni nazw std?
W poniższym kodzie definiuję trywialną funkcję log
. W main
staram się , a nie nazywać go; wzywam std::log
. Niemniej jednak, mój własny log
jest nazywany; i widzę " log!"na ekranie. Czy ktoś wie dlaczego? Używam G++ 4.7 i clang++ 3.2.
#include <iostream>
#include <cmath>
double log(const double x) { std::cout << "log!\n"; return x; }
int main(int argc, char *argv[])
{
std::log(3.14);
return 0;
}
5 answers
C++ Standard 17.6.1.2 paragraf 4 (podkreślenie):
Z wyjątkiem przypadków wymienionych w pkt 18-30 i załączniku D, zawartość każdego nagłówka
cname
jest taka sama jak zawartość odpowiedniego nagłówkaname.h
, Jak określono w bibliotece standardowej C (1.2) lub w C Unicode TR, stosownie do przypadku, tak jakby przez włączenie. W bibliotece standardowej C++ deklaracje (z wyjątkiem nazw, które są zdefiniowane jako makra w C) znajdują się w obszarze przestrzeni nazw (3.3.6) przestrzeni nazwstd
. nie jest określone, czy te nazwy są najpierw zadeklarowane w globalnym zakresie przestrzeni nazw, a następnie są wstrzykiwane do przestrzeni nazw {[2] } przez jawne za pomocą-declarations (7.3.3).
G++ robi to w ten drugi sposób, aby niektóre z tych samych plików nagłówkowych mogły być ponownie użyte w C i C++. Tak więc g++ może deklarować i definiować double log(double)
w globalnej przestrzeni nazw.
Sekcja 17.6.4.3.3 ustępy 3 i 4:
Każda nazwa ze standardowej biblioteki C zadeklarowana z linkiem zewnętrznym jest zarezerwowana dla implementacji do użycia jako nazwa z linkiem
extern "C"
, zarówno w przestrzeni nazwstd
, jak i w globalnej przestrzeni nazw.Każda sygnatura funkcji ze standardowej biblioteki C zadeklarowanej z zewnętrznymi powiązaniami jest zarezerwowana dla implementacji do użycia jako sygnatura funkcji z powiązaniami
extern "C"
iextern "C++"
, lub jako nazwa zakresu przestrzeni nazw w globalnej przestrzeni nazw.
I na górze sekcji 17.6.4.3 pkt 2:
Ty natomiast możesz Nie deklarować ani definiowaćJeśli program deklaruje lub definiuje nazwę w kontekście, w którym jest zarezerwowana, innym niż wyraźnie dozwolony przez tę klauzulę, jego zachowanie jest niezdefiniowane.
::log
w jakikolwiek sposób.
Szkoda, że łańcuch narzędzi g++ nie daje żadnych komunikatów o błędach.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-08-09 23:02:46
Spodziewam się, że std::log
po prostu deleguje się do ::log
. Niestety, ::log
zapewnia tylko float
przeciążenie, a Ty uprzejmie zapewniasz double
przeciążenie, dzięki czemu Twoje lepiej pasuje. Ale nadal nie widzę, jak to się w ogóle bierze pod uwagę w zestawie przeciążeniowym.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-08-09 22:46:28
W libstdc++'s cmath
zobaczysz to:
using ::log;
/ Align = "left" / funkcje h z globalnej przestrzeni nazw do std
. Niestety dostarczasz implementację dla double log(double)
, więc linker nie będzie używał tej z biblioteki matematycznej. EDIT: twierdzę, że jest to błąd w libstdc++, ponieważ std::log
nie powinien cierpieć z powodu ingerencji w bibliotekę C, gdy wyraźnie prosisz o wersje std::
. Oczywiście, tędy. aby nadpisać funkcje biblioteki standardowej jest stara "funkcja"z języka C.
EDIT 2: dowiedziałem się, że standard nie zabrania wprowadzania nazw z globalnej przestrzeni nazw do std
. Nie jest to więc jednak błąd, a jedynie konsekwencja szczegółów implementacji.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-08-09 22:58:18
W C++ kompilator może dowolnie implementować bibliotekę C w globalnej przestrzeni nazw i delegować do niej (jest to implementacja zdefiniowana).
17.6.1.2.4 z wyjątkiem przypadków wymienionych w pkt 18-30 i załączniku D, zawartość każdego nagłówka cname jest taka sama jak nazwa odpowiedniego nagłówka.h, jak określono w bibliotece standardowej C (1.2) lub w Unicode C TR, w stosownych przypadkach, tak jakby przez włączenie. W bibliotece standardowej C++, jednak deklaracje (z wyjątkiem nazwy zdefiniowane jako makra w języku C) znajdują się w obszarze przestrzeni nazw (3.3.6) std. jest nie jest określone, czy te nazwy są najpierw deklarowane w globalnym zakresie przestrzeni nazw, a następnie wstrzykiwane do przestrzeni nazw std poprzez jawne użycie-deklaracje (7.3.3).
Ogólnie rzecz biorąc, unikałbym tworzenia funkcji z tym samym podpisem, co jedna z bibliotek standardu C. standard C++ z pewnością daje kompilatorom swobodę używania tych podpisów, jeśli tak wybierze, co oznacza, że możesz walczyć ze swoim kompilatorem, jeśli spróbujesz użyć tych samych podpisów. Stąd masz dziwne wyniki.
Spodziewałbym się jednak błędu linkera lub ostrzeżenia i myślę, że warto to zgłosić.
[edytuj]
Wow, ninja ' D.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-08-09 23:06:29
Ponieważ nadpisałeś go w globalnej przestrzeni nazw. Użycie przestrzeni nazw pozwala uniknąć tego niebezpieczeństwa, jeśli nie chcesz przejść do bezpieczniejszego, czystszego języka, takiego jak na przykład Nim .
Właściwe użycie przestrzeni nazw demo :
#include <iostream>
#include <cmath> // Uses ::log, which would be the log() here if it were not in a namespace, see http://stackoverflow.com/questions/11892976/why-is-my-log-in-the-std-namespace
// Silently overrides std::log
//double log(double d) { return 420; }
namespace uniquename {
using namespace std; // So we don't have to waste space on std:: when not needed.
double log(double d) {
return 42;
}
int main() {
cout << "Our log: " << log(4.2) << endl;
cout << "Standard log: " << std::log(4.2);
return 0;
}
}
// Global wrapper for our contained code.
int main() {
return uniquename::main();
}
Wyjście:
Our log: 42
Standard log: 1.43508
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-06 01:51:41