Недавно я узнал, что оператор .*
(и тесно связанный с ним оператор ->*
) существует в C++. (См. этот вопрос.)
На первый взгляд кажется аккуратным, но зачем мне это вообще нужно? Два ответа на связанный вопрос предоставили надуманные примеры, которые выиграли бы от прямого вызова функции.
Если прямой вызов функции неудобен, вместо него можно использовать функциональный объект, например лямбда-функции, которые можно использовать в std::sort
. Это устраняет уровень косвенности и, следовательно, будет более производительным, чем использование .*
.
В связанном вопросе также упоминается упрощенная версия этого примера:
struct A {
int a;
int b;
};
void set_member(A& obj, int A::* ptr, int val){
obj.*ptr = val;
}
int main()
{
A obj;
set_member(obj, &A::b, 5);
set_member(obj, &A::a, 7);
// Both members of obj are now assigned
}
Но это довольно тривиально (возможно, даже лучше, потому что это чище и не ограничивается членами A
без необходимости) сделать это вместо этого:
struct A {
int a;
int b;
};
void set_me(int& out, int val){
out = val;
}
int main()
{
A obj;
set_me(obj.b, 5);
set_me(obj.a, 7);
// Both members of obj are now assigned
}
В заключение, указатель на функцию-член может быть заменен функциональным объектом, а указатель на переменную-член может быть заменен прямой ссылкой на указанную переменную или объект функции. Это также может повысить эффективность кода из-за меньшего количества косвенных обращений.
Этот вопрос содержит только примеры, подтверждающие мой вывод, поэтому это так не отвечайте на мой вопрос.
Помимо взаимодействия с унаследованным кодом, который использует .*
(в котором вообще не было бы выбора), когда, на самом деле, я хотел бы использовать .*
?
std::sort()
, или просто неконстантная ссылка. - person Bernard   schedule 28.06.2017PropertyImpl
, который является Callable, принимающим один параметр типаClass
и возвращающим ссылку на правильный элемент. В конце концов, вы уже используете шаблоны. Таким образом, тип элемента кортежа инкапсулирует достаточную информацию, чтобы уже найти правильный член, устраняя необходимость хранить указатель на член. - person Bernard   schedule 28.06.2017property([] (Dog& x) -> decltype(x.barktype) { return x.barktype; });
, для чего не потребуетсяconstexpr
, потому что параметрx
неизвестен во время компиляции. Или дажеproperty([] (auto&& x) -> decltype(std::forward<decltype(x)>(x).barktype) { return std::forward<decltype(x)>(x).barktype; });
, но это довольно долго. - person Bernard   schedule 28.06.2017&Dog::barktype
гораздо менее подробным, чем[] (Dog& d) -> decltype(d.barktype) { return d.barktype }
- person Guillaume Racicot   schedule 28.06.2017