Ничего себе. C++ никогда не прекращает удивлять меня своей странностью.
В шаблонном определении, дисквалифицированные имена больше не будут находить членов зависимой основы (как определено [temp.dep]/3 в стандарте C++). Например,
template <typename T> struct B {
int m;
int n;
int f ();
int g ();
};
int n;
int g ();
template <typename T> struct C : B<T> {
void h ()
{
m = 0; // error
f (); // error
n = 0; // ::n is modified
g (); // ::g is called
}
};
необходимо сделать зависимого имен, например, путем добавления префикса их это->. Вот исправленное определение C:: h,
template <typename T> void C<T>::h ()
{
this->m = 0;
this->f ();
this->n = 0
this->g ();
}
Как альтернативное решение (к сожалению, не назад совместимый с GCC 3.3), можно использовать объявления использования вместо этого->:
template <typename T> struct C : B<T> {
using B<T>::m;
using B<T>::f;
using B<T>::n;
using B<T>::g;
void h ()
{
m = 0;
f ();
n = 0;
g ();
}
};
Это - просто все виды сумасшедших. Спасибо, David.
Вот "temp.dep/3" раздел стандарта [ISO/IEC 14882:2003], к которому они обращаются:
В определении шаблона класса или члене шаблона класса, если базовый класс шаблона класса зависит от шаблонного параметра, объем базового класса не исследован во время неполного поиска имени или при определении шаблона класса или при участнике или во время инстанцирования шаблона класса или участника. [Пример:
typedef double A;
template<class T> class B {
typedef int A;
};
template<class T> struct X : B<T> {
A a; // a has typedouble
};
имя типа
A
в определенииX<T>
связывает с именем определения типа, определенным в объеме глобального пространства имен, не к имени определения типа, определенному в базовом классеB<T>
.] [Пример:
struct A {
struct B { /* ... */ };
int a;
int Y;
};
int a;
template<class T> struct Y : T {
struct B { /* ... */ };
B b; //The B defined in Y
void f(int i) { a = i; } // ::a
Y* p; // Y<T>
};
Y<A> ya;
участники
A::B
,A::a
, иA::Y
из аргумента шаблонаA
не влияют на привязку имен в [1 112].]
Нет, часть B == 2
не оценивается. Это называется оценкой короткого замыкания .
Редактировать: Как Роберт К. Картаино справедливо указывает , если логический оператор перегружен, оценка короткого замыкания не выполняется имеют место (как уже было сказано, я не понимаю, почему кто-то перегружает логический оператор).
Если оператор ||
не перегружен , второе выражение не будет оцениваться. Это называется «оценкой короткого замыкания».
В случае логического И (&&) и логического ИЛИ (||) второе выражение не будет оцениваться, если первого выражения достаточно для определения значения всего выражение.
В случае, описанном выше:
if(A == 1 || B == 2) {...}
... второе выражение не будет оцениваться, потому что
TRUE || ANYTHING
всегда оценивается как TRUE
.
Аналогично,
FALSE && ANYTHING
, всегда оценивается как FALSE
, так что это условие также вызовет оценка короткого замыкания .
&&
и ||
]. Часть B == 2 не оценивается.
Будьте осторожны! Не помещайте туда что-то вроде ++ B == 2!
C ++ применяет сокращение к вычислению логического выражения, поэтому B == 2
никогда не вычисляется, и компилятор может даже полностью его опустить.
Компилятор обрабатывает это, генерируя промежуточные переходы. Для следующего кода:
if(A == 1 || B == 2){...}
, скомпилированный в псевдоассемблер, может быть:
load variable A
compare to constant 1
if equal, jump to L1
load variable B
compare to constant 2
if not equal, jump to L2
L1:
... (complete body of if statement)
L2:
(code after if block goes here)
Это оценка короткого замыкания , как говорит Джеймс. Ленивое вычисление - это совсем другое.
B == 2
никогда не оценивается.
См. Оценка короткого замыкания для получения дополнительной информации.
Нет, это не так.
То же самое с &&
, если одно неверно, другое не беспокоит.