Указатель на темпоральный объект

Jul 15, 2014 11:23

Появился тут кодец, который, если упростить его до безобразия, выглядит так:

struct X
{
};

class A
{
public:
A(const X* x) {}
};

class B : public A
{
public:
B() : A(&X()) {}
};

Ну то есть есть класс A, который конструктором принимает некоторую структуру для целей собственной инициализации (параметры инициализации там лежат, чтобы не рисовать большой-пребольшой конструктор), а есть класс B, который хочет проинициализировать свою базу A такой структурой, а при этом своих клиентов он грузить подробностями не хочет. Соответственно классу B нужно успеть создать такую структуру в узкий промежуток между вызовом B::B и передачей управления A::A, а узкий промежуток заключается только в вычислении параметров A::A, соответственно придумать что-то умнее, как создать темпоралку X и передать ее в A, сложно.

Проблема же в том, что A принимает не константную ссылку на X, а константный указатель, и если визуальнику на это пофиг, то остальным компилятором нет, и они справедливо указывают на пункт стандарта, который утверждает, что операндом & должно быть lvalue (а темпоралка им не является). Вопрос -- как быть? Если можно поменять A, то задачки нет, а предположим A поменять нельзя. Какие есть варианты?

1) Если бы можно было бы где-то написать хотя бы стейтмент, то можно было бы написать так

const X& x = X();
A(&x)

но это не наш кейс

2) Если можно было бы изменить X, то можно было бы приписать ей функцию

const X* ptr() const { return this; }

и, соответственно, вызов заменить на

B(): A(X().ptr()) {}

3) Можно не меняя X пронаследовать его, а в наследнике сделать такую функцию

struct Y : X
{
const X* ptr() const { return this; }
};

и, соответственно, вызов заменить на

B() : A(Y().ptr()) {}

4) Можно написать шаблончик, который возьмет const X&, и вернет указатель

template const T* ptr(const T& t) { return &t; }

и, соответственно, вызов заменить на

B() : A(ptr(X())) {}

5) И, наконец, мой фаворит. Написать лямбду, которая делает то же самое

B() : A([](const X& x){ return &x; }(X())) {}

И все.

prog

Previous post Next post
Up