C3536 нельзя использовать до инициализации - PullRequest
0 голосов
/ 03 августа 2020

Я работаю над старым проектом исходного кода, который изначально был написан с использованием MSV C 2008 и Boost 1.42, сегодня я пытаюсь перенести его на MSV C 2017 с Boost 1.73

Там необходимо решить множество проблем, одна из которых приведена ниже:

Severity    Code    Description Project File    Line    Suppression State
Error   C3536   'binding': cannot be used before it is initialized  Process Control Service Group   processscope.cpp    197 

Строка, в которой это происходит:

auto binding = boost::bind(&IProcessChangeObserver::notify, _1, m_scope, change);
std::for_each(observers.begin(), observers.end(), binding);

Первоначально назначение привязки было встроено в качестве третьего параметра, это дает ту же ошибку. Я понимаю, почему это проблема, я не понимаю, почему это когда-либо сработало?

Есть ли другой способ написать выше, не вызывая предупреждения?

Я попытался заменить на стандартный l oop:

for( std::list<boost::intrusive_ptr<IProcessChangeObserver> >::iterator itProc=objservers.begin();
     itProc!=objservers.end(); itProc++ ) {
    boost:bind(&IProcessChangeObserver::notify, itProc, m_scope, change);
}

Если честно, я не на 100% уверен, подходит ли это для подобной замены?

Ответы [ 2 ]

0 голосов
/ 06 августа 2020

Фактическое исправление заключалось в том, чтобы просто заменить _1 на std :: placeholder :: _ 1

0 голосов
/ 04 августа 2020

У меня есть подозрение, что настоящая проблема связана с binding, который, вероятно, неправильно инициализирован. Об этом должно быть больше сообщений компилятора.

Это могло быть потому, что Boost Bind перестала помещать заполнители _1 в глобальное пространство имен по умолчанию. Вы можете обнаружить это, добавив -DBOOST_BIND_GLOBAL_PLACEHOLDERS к флагам компилятора. Однако прислушайтесь к совету из кода:

BOOST_PRAGMA_MESSAGE(
  "The practice of declaring the Bind placeholders (_1, _2, ...) "
  "in the global namespace is deprecated. Please use "
  "<boost/bind/bind.hpp> + using namespace boost::placeholders, "
  "or define BOOST_BIND_GLOBAL_PLACEHOLDERS to retain the current behavior."
)

Минимальное воспроизведение

Посмотрим, сможете ли вы воспроизвести с помощью этого минимального репродуктора (я не могу, но у меня нет доступа к необходимым версиям MSVC / Boost):

Live ON Coliru - G CC

Live On Rextester - MSV C

#include <algorithm>
#include <iostream>
#include <list>
#include <boost/bind/bind.hpp>
using namespace boost::placeholders;
#include <boost/intrusive_ptr.hpp>
#include <boost/smart_ptr/intrusive_ref_counter.hpp>
struct Scope {};
struct Change {};

namespace MyLib {
    struct IProcessChangeObserver
        : boost::intrusive_ref_counter<IProcessChangeObserver>
    {
        virtual ~IProcessChangeObserver() = default;
        virtual void notify(Scope, Change) = 0;
    };

    struct Obs1 : IProcessChangeObserver {
        void notify(Scope, Change) override { std::cout << "Obs1\n"; }
    };
    struct Obs2 : IProcessChangeObserver {
        void notify(Scope, Change) override { std::cout << "Obs2\n"; }
    };
}

using ObserverPtr = boost::intrusive_ptr<MyLib::IProcessChangeObserver>;

int main() {
    using namespace MyLib;
    std::list<ObserverPtr> observers {
        new Obs1(), new Obs2(), new Obs1(),
    };

    Scope m_scope;
    Change change;
    auto binding = boost::bind(&IProcessChangeObserver::notify, _1, m_scope, change);
    std::for_each(observers.begin(), observers.end(), binding);
}

Печать

Obs1
Obs2
Obs1
...