Вы можете посмотреть Seam (см. в этой статье для обсуждения использования Seam с JSF и AJAX).
Когда я использовал Судя по всему, в последний раз это было довольно медленно. Возможно, вы захотите создать свой собственный компонент JSF, который генерирует JavaScript (например, используя jQuery, как описано в в этой статье ).
Членом выражения rvalue является значение rvalue.
Стандарт заявляет в 5.3.5 [expr.ref]:
Если объявлено, что E2 имеет тип «ссылка на T», то E1.E2 является lvalue [...] - Если E2 является нестатическим членом данных, а тип E1 - «cq1 vq1 X», а тип E2 - «cq2 vq2 T», выражение обозначает именованный член объекта, обозначенный первым выражением. Если E1 является lvalue, то E1.E2 является lvalue.
Это хорошее время, чтобы узнать, что такое xvalues и glvalues .
R-значения могут быть двух типов - , значения и , значения . В соответствии с новым стандартом C ++ 17
prvalue - это выражение, вычисление которого инициализирует объект, битовое поле или операнд оператора, как указано в контексте в котором оно появляется.
, поэтому что-то вроде fun()
в вашем примере оценивается как prvalue (который является r-значением). Это также говорит нам, что fun().v
не является prvalue, так как это не ванильная инициализация.
X-значения , которые также являются r-значениями, определяются так
xvalue (значение «eXpiring») также относится к объекту обычно ближе к концу срока службы (например, ресурсы можно переместить). Определенные виды выражений, включающие ссылки на rvalue (8.3.2), дают значения xvalue. [Пример: Результатом вызова функции, возвращаемый тип которой является rvalue-ссылкой на тип объекта, является xvalue (5.2.2). - конец примера]
В дополнение к rvalues, еще одной зонтичной категорией значений является glvalue , которые бывают двух типов xvalues и традиционные lvalues .
На данный момент мы определили категории основных значений. Это может быть визуализировано следующим образом
Категория glvalue может широко означать, что lvalues должны были означать до того, как семантика перемещения стала вещью - вещью, которая может быть в левой части выражения. glvalue означает обобщенное lvalue.
Если мы посмотрим на определение значения xvalue , то оно говорит, что что-то является значением xvalue , если оно подходит к концу своего времени жизни. В вашем примере, fun().v
подходит к концу своего времени жизни. Таким образом, его ресурсы могут быть перемещены. И поскольку его ресурсы можно перемещать, это не lvalue, поэтому ваше выражение вписывается в единственную оставшуюся категорию значений листьев - xvalue .
Это становится очевидным, если учесть, что компилятор сгенерирует для вас конструктор по умолчанию, конструктор копирования по умолчанию и оператор назначения копирования по умолчанию, если ваша структура / класс не содержит ссылочных членов. Затем подумайте, что стандарт позволяет вам вызывать методы-члены для временных переменных, то есть вы можете вызывать неконстантные члены для неконстантных временных.
См. Этот пример:
struct Foo {};
Foo foo () {
return Foo();
}
struct Bar {
private:
Bar& operator = (Bar const &); // forbid
};
Bar bar () {
return Bar();
}
int main () {
foo() = Foo(); // okay, called operator=() on non-const temporarie
bar() = Bar(); // error, Bar::operator= is private
}
Если вы напишите
struct Foo {};
const Foo foo () { // return a const value
return Foo();
}
int main () {
foo() = Foo(); // error
}
т.е. если вы позволите функции foo () вернуть const временно, тогда произойдет ошибка компиляции.
Чтобы завершить пример, вот как вызывается член const temporarie:
struct Foo {
int bar () const { return 0xFEED; }
int frob () { return 0xFEED; }
};
const Foo foo () {
return Foo();
}
int main () {
foo().bar(); // okay, called const member method
foo().frob(); // error, called non-const member of const temporary
}
Вы можете определить время жизни временного элемента, которое будет в текущем выражении. И вот почему вы также можете изменять переменные-члены; если вы не можете, то возможность вызова неконстантных методов-членов будет приведена до абсурда.
Редактировать: И вот необходимые ссылки:
12.2 Временные объекты:
, а затем (или лучше, раньше)
3.10 L-значения и значения:
И пример использования: http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Named_Parameter
Я заметил, что в gcc, как правило, очень мало вычислений по поводу использования rvalue в качестве lvalue в выражениях присваивания. Это, например, прекрасно компилируется:
class A {
};
extern A f();
void g()
{
A myA;
f() = myA;
}
Почему это законно, а это нет (то есть не компилируется), хотя меня действительно смущает:
extern int f();
void g()
{
f() = 5;
}
ИМХО, стандартный комитет может кое-что объяснить в отношении lvalues , rvalues и где их можно использовать. Это одна из причин, почему меня так интересует этот вопрос о rvalue .
В вашем коде нет сцены. Возвращенная структура размещается в стеке, поэтому результат присваивания будет немедленно потерян.
Ваша функция должна eiter выделить новый экземпляр A следующим образом:
new A()
В этом случае лучшая подпись
A* f(){ ...
Или вернуть существующий экземпляр, например:
static A globalInstance;
A& f(){
return globalInstance;
}
Edit: Ok, кажется, у меня наконец-то есть что-то из стандарта:
Обратите внимание, что v
имеет тип int
, который имеет встроенный оператор присваивания:
13.3.1.2 Операторы в выражениях
4 Для встроенных операторов присваивания преобразования левого операнда ограничены следующим образом: - не вводятся временные элементы для хранения левого операнда, и [...]
fun1()
должен возвращать ссылку. Возвращаемый тип функции, не являющийся ссылкой/указателем, является r-значением.
3.10 L-значения и r-значения
5 Результатом вызова функции, которая не возвращает ссылку на l-значение, является r-значение [...]
Таким образом, fun1().v
является r-значением.
8.3.2 Ссылки
2 Ссылочный тип, объявленный с использованием & называется ссылкой lvalue, а ссылочный тип, объявленный с использованием && называется rvalue ссылкой. Ссылки lvalue и rvalue references - это разные типы.