Как сделать повышение:: make_shared друг моего класса

Я записал класс с защищенным конструктором, так, чтобы новые экземпляры могли только быть произведены с помехами, создают () функцию, которая возвращает shared_ptr моему классу. Для обеспечения эффективного выделения, я хотел бы использовать повышение:: make_shared в создать функции, однако компилятор жалуется, что мой конструктор класса защищен в повышении:: make_shared. Я решил к своему повышению:: make_shared друг моего класса, но я озадачен о синтаксисе. Я попробовал

template< class T, class A1, class A2 >
friend boost::shared_ptr<Connection> boost::make_shared(const ConnectionManagerPtr&, const std::string&);

но компилятор дал мне синтаксические ошибки. Помогите.

9
задан kyku 31 July 2010 в 14:31
поделиться

4 ответа

Вам не нужно шаблонизировать часть friend, но вам нужно указать, что функция friend является шаблоном:

friend boost::shared_ptr<Connection> boost::make_shared<>(/* ... */);
//                                                     ^^

Это работает с Comeau и текущими версиями GCC, но не работает с VC. Лучше было бы использовать следующую форму:

friend boost::shared_ptr<Connection> boost::make_shared<Connection>(/* ... */);

Теперь это работает на нескольких компиляторах - я тестировал это на VC8, VC10, GCC 4.2, GCC 4.5 и Comeau 4.3.

Альтернативный вариант - использование квалифицированного имени для ссылки на конкретный экземпляр шаблона функции, как это делает Мартин, должно работать и работает в Comeau, но GCC подавляет его.

Полезная альтернатива, которая не зависит от деталей реализации make_shared() (и поэтому также работает с реализацией VC10s TR1) - использовать pass-key-idiom для защиты доступа к конструктору и подружиться с create() функцией вместо этого, например. например:

class Connection {
// ...
public:
    class Key {
        friend boost::shared_ptr<Connection> create(const ConnectionManagerPtr&, 
                                                    const std::string&);
        Key() {}
    };
    Connection(const ConnectionManagerPtr&, const std::string&, const Key&);
};

boost::shared_ptr<Connection> create(const ConnectionManagerPtr& p, 
                                     const std::string& s) 
{
    return boost::make_shared<Connection>(p, s, Connection::Key());
}
10
ответ дан 4 December 2019 в 14:26
поделиться

Я бы попробовал без части шаблона . В конце концов, вы же хотите, чтобы конкретный экземпляр функции (шаблона) был другом вашего класса, не так ли?

friend boost::shared_ptr<Connection> boost::make_shared(const ConnectionManagerPtr&, const std::string&);

работает?

Если это не решение, было бы полезно передать нам сообщения компилятора, которые вы получаете ...

2
ответ дан 4 December 2019 в 14:26
поделиться

Я думаю, что это не самое подходящее место для использования make_shared. Просто создайте объект с помощью оператора new и передайте указатель в конструктор shared_ptr. Таким образом, вам не нужно будет ни с кем дружить.

BTW, почему аргументы шаблона и аргументы функции имеют разный тип?

2
ответ дан 4 December 2019 в 14:26
поделиться

Краткое описание того, как может выглядеть полная версия:

#include <iostream>
#include <boost/make_shared.hpp>

class Foo {
  explicit Foo(int x) {
    std::cout << "Foo::Foo(" << x << ")\n";
  }
public:
  friend boost::shared_ptr<Foo> boost::make_shared<Foo, int>(const int& x);

  static boost::shared_ptr<Foo> create(int x) {
    return boost::make_shared<Foo, int>(x);
  }

  ~Foo() {
    std::cout << "Foo::~Foo()\n";
  }
};

int main(int argc, const char *argv[]) {
  Foo::create(42);
}
-1
ответ дан 4 December 2019 в 14:26
поделиться
Другие вопросы по тегам:

Похожие вопросы: