Как дать контейнер в качестве аргумента сервисам

Проблемы:

1) Если функция view определена как:

void view(std::ostream output, std::string text) // (1)
{
    output << text;
}

И используется:

view(std::cout, "Hello, World!"); // (2)

Тогда сообщение об ошибке задается компилятором:

В MSVC:

error C2280: 'std::basic_ostream>::basic_ostream(const std::basic_ostream> &)': attempting to reference a deleted function

blockquote>

GCC:

error: use of deleted function 'std::basic_ostream<_CharT, _Traits>::basic_ostream(const std::basic_ostream<_CharT, _Traits>&) [with _CharT = char; _Traits = std::char_traits]'

blockquote>

Clang:

error: call to deleted constructor of 'std::ostream' (aka 'basic_ostream')

blockquote>

2) Для объявления

std::ostream os;
[1137 ] Отображается следующее сообщение об ошибке:

MSVC:

error C2512: 'std::basic_ostream>': no appropriate default constructor available

blockquote>

GCC:

[ 1110]

blockquote>

Clang:

error: calling a protected constructor of class 'std::basic_ostream'

blockquote>

Причина:

Это все в соответствии со спецификацией std :: basic_ostream

Нет определения для конструктора по умолчанию - поэтому переменная типа std::ostream не может быть создана без конкретных параметров конструктора. [ 1145]

И, как говорится в C ++ Reference, о конструкторе копирования std :: basic_ostream :

Конструктор копирования защищен и удален. Выходные потоки не копируются.

blockquote>

Объяснение:

1) Итак, проблема в том, что в (2) параметр std::cout был передан функции, которая определена в (1) скопировать std::ostream в переменную output.

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

2) В случае создания переменной os - она ​​не дает никаких параметров конструктора, нет конструктора по умолчанию, поэтому компилятор выдает сообщение об ошибке.


Как это исправить?

1) В объявлении функции измените определение, чтобы в качестве параметра взять ссылку (&) на std::ostream:

[113 ]

Это позволяет ему использовать оригинальный объект вместо копирования (что копирование запрещено).


2) Если требуется переменная, то также следует использовать ссылку;

std::ostream& out = std::cout;

29
задан 05.05.2020, 22:30

2 ответа

Добавить:

<argument type="service" id="service_container" />

И в вашем классе слушателя:

use Symfony\Component\DependencyInjection\ContainerInterface;

//...

public function __construct(ContainerInterface $container, ...) {
47
ответ дан 05.05.2020, 22:31
  • 1
    Если you' ре в контроллере и потребности преобразовать из текста для строкового представления это очень удобно. – Jerome 03.01.2016, 06:04
  • 2
    Спасибо! это работает хорошо! – whitebear 05.05.2020, 22:32

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

<?php

namespace iBasit\ToolsBundle\Utils\Lib;

use Doctrine\Bundle\DoctrineBundle\Registry;
use Symfony\Component\DependencyInjection\ContainerInterface;

trait Container
{
    private $container;

    public function setContainer (ContainerInterface $container)
    {
        $this->container = $container;
    }

    /**
     * Shortcut to return the Doctrine Registry service.
     *
     * @return Registry
     *
     * @throws \LogicException If DoctrineBundle is not available
     */
    protected function getDoctrine()
    {
        if (!$this->container->has('doctrine')) {
            throw new \LogicException('The DoctrineBundle is not registered in your application.');
        }

        return $this->container->get('doctrine');
    }

    /**
     * Get a user from the Security Token Storage.
     *
     * @return mixed
     *
     * @throws \LogicException If SecurityBundle is not available
     *
     * @see TokenInterface::getUser()
     */
    protected function getUser()
    {
        if (!$this->container->has('security.token_storage')) {
            throw new \LogicException('The SecurityBundle is not registered in your application.');
        }

        if (null === $token = $this->container->get('security.token_storage')->getToken()) {
            return;
        }

        if (!is_object($user = $token->getUser())) {
            // e.g. anonymous authentication
            return;
        }

        return $user;
    }

    /**
     * Returns true if the service id is defined.
     *
     * @param string $id The service id
     *
     * @return bool true if the service id is defined, false otherwise
     */
    protected function has ($id)
    {
        return $this->container->has($id);
    }

    /**
     * Gets a container service by its id.
     *
     * @param string $id The service id
     *
     * @return object The service
     */
    protected function get ($id)
    {
        if ('request' === $id)
        {
            @trigger_error('The "request" service is deprecated and will be removed in 3.0. Add a typehint for Symfony\\Component\\HttpFoundation\\Request to your controller parameters to retrieve the request instead.', E_USER_DEPRECATED);
        }

        return $this->container->get($id);
    }

    /**
     * Gets a container configuration parameter by its name.
     *
     * @param string $name The parameter name
     *
     * @return mixed
     */
    protected function getParameter ($name)
    {
        return $this->container->getParameter($name);
    }
}

Ваш объект, который будет обслуживать.

namespace AppBundle\Utils;

use iBasit\ToolsBundle\Utils\Lib\Container;

class myObject
{
    use Container;
}

Настройки вашего сервиса

 myObject: 
        class: AppBundle\Utils\myObject
        calls:
            - [setContainer, ["@service_container"]]

Позвоните в сервис в контроллере

$myObject = $this->get('myObject');
14
ответ дан 05.05.2020, 22:31
  • 1
    Я соглашаюсь, it' s определенно клиентская вещь (в большинстве случаев, в отличие от, скажем, индексных комментариев MySQL). Но что происходит, когда клиент не является HTML5 и скорее ObjC или Java? – Nate Symer 18.06.2014, 05:05

Теги

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