I am working on an old source code project which originally was written using MSVC 2008 and Boost 1.42, today I'm trying to port this to MSVC 2017 with Boost 1.73
There are many issues to resolve, one of which is below:
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
The line that this occurs on:
auto binding = boost::bind(&IProcessChangeObserver::notify, _1, m_scope, change);
std::for_each(observers.begin(), observers.end(), binding);
Originally the assignment to binding was inline as the third parameter, it gives the same error. I can see why this is a problem, I cannot see why it ever worked?
Is there another way to write the above without the triggering a warning?
I've tried replacing with a standard loop:
for( std::list<boost::intrusive_ptr<IProcessChangeObserver> >::iterator itProc=objservers.begin();
itProc!=objservers.end(); itProc++ ) {
boost:bind(&IProcessChangeObserver::notify, itProc, m_scope, change);
}
To be honest I'm not 100% sure if this is a like for like replacement?
I have a suspicion the real problem is with binding which is likely not correctly initialized. There's bound to be more compiler messages about that.
It could be because Boost Bind stopped putting the _1 placeholders in the global namespace by default. You might detect this by adding -DBOOST_BIND_GLOBAL_PLACEHOLDERS to the compiler flags. However, heed the advice from the code:
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."
)
Minimal repro
See if you can reproduce with this minimal reproducer (I can't but I don't have access to the requisite versions ofr MSVC/Boost):
Live ON Coliru - GCC
Live On Rextester - MSVC
#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);
}
Prints
Obs1
Obs2
Obs1
The actual fix was just to change _1 to std::placeholders::_1
Related
I'm pretty sure I'm probably doing something stupid, but I've been at this an hour and a half and can't figure out what I'm missing.
I can create an object from my class using the default constructor, but can't use an overloaded constructor when I add one. I can't call the print member function that I have included or any others that I have tried to include either. I have put the three files into a Code::Blocks project and gotten the same result. I have also tried the three files on Dev-Cpp with the same result. Any help would be greatly appreciated.
Main Function
#include <iostream>
#include "Appt.h"
using namespace std;
int main()
{
Appt a();
a.print();
}
Appt.h
#ifndef APPT_H
#define APPT_H
#include <iostream>
#include <string>
using namespace std;
class Appt
{
public:
Appt();
void print();
private:
string description;
};
#endif // APPT_H
Appt.cpp
#include "Appt.h"
using namespace std;
Appt::Appt()
{
description = "No Description";
}
void Appt::print()
{
cout << description << endl;
}
I am using Code::Blocks 16.01 with the GCC compiler. These files are not currently in a project. I am also running Windows 7.
It looks like your problems may be related to this line:
Appt a();
Unfortunately, while this looks like it calls the default constructor, it actually declares a to be of type Appt(), that is, a function taking no arguments and returning Appt. If you want to call the default constructor, there are a few options:
Appt a;
Appt a = Appt();
Appt a{}; // requires C++11
I would prefer the last one.
I was attempting to follow the example of Finite State Filters in the Boost::iostreams documentation. However when I went to use the filter I got an error stating the ::imbue was not accessible because 'boost::iostreams::detail::finite_state_filter_impl' uses 'protected' to inherit from 'my_fsm'.
Frustrated I copied my code into the tests used to in the boost examples. The tests compile and pass. My conculsion is that I am probably mis-using the dual use filter defined by:
typedef io::finite_state_filter my_fsm_filter;
I feel that just pushing it onto a filtered_stream may not be proper, but I could not find a missing step. I am sure there must be a need to wrap the filter but I can find no example (though I am sure if I dug deep enough into the code used to test the boost code it has to be there somewhere).
here is a bit of example code:
#include <boost/mpl/vector.hpp>
#include <libs/iostreams/example/finite_state_filter.hpp>
namespace io = boost::iostreams;
struct my_fsm : io::finite_state_machine<my_fsm> {
BOOST_IOSTREAMS_FSM(my_fsm) // define skip and push.
typedef my_fsm self;
static const int beginline = 0;
static const int skipline = 1;
static const int dataline = 2;
typedef boost::mpl::vector <
row<beginline, is<'C'>, skipline, &self::skip>,
row<beginline, is_any, dataline, &self::push>,
row<skipline, is<'\n'>, beginline, &self::skip>,
row<skipline, is_any, skipline, &self::skip>,
row<dataline, is<'\n'>, beginline, &self::push>,
row<dataline, is_any, dataline, &self::push>
> transition_table;
};
typedef io::finite_state_filter<my_fsm> my_fsm_filter;
#include <iostream>
#include <string>
#include <boost/iostreams/device/file.hpp>
#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/stream.hpp>
namespace io = boost::iostreams;
int main() {
io::stream<io::file_sink> out(io::file_sink("outputfile.txt"));
io::filtering_istream in;
my_fsm_filter infsm;
in.push(my_fsm_filter());
in.push(io::file_source("inputdata.txt"));
while (in) {
std::string line;
if(std::getline(in, line)) {
//std::cout << line << std::endl;
out << line << std::endl;
}
}
return 0;
}
I personally feel that there is a bug in the sample header with respect to this imbue call.
However, you can work around it by changing the typedef to
struct my_fsm_filter : io::finite_state_filter<my_fsm> {
using io::finite_state_filter<my_fsm>::imbue;
};
This explicitly exposes the imbue method as public on the derived type. I haven't looked at the sample program that you reported to be working (because you didn't link to it). But it's possible they used a similar hack.
In my tests, a similar edit to finite_state_filte.hpp L278 to add
using base_type::imbue;
to class finite_state_filter has the same effect.
This is really driving me crazy:
#include <iostream>
#include <vector>
#include <string.h>
#include <thread>
using namespace std;
void test() {
vector<string> myvector;
string a("Teststring");
myvector.push_back(a);
cout << myvector.begin()->length() << endl;
}
int main() {
thread(test).join();
return 0;
}
The code compiles fine with the -std=c++11 flag to the compiler and the -pthread flag to the linker.
BUT: Eclipse does either know the std::thread or the myvector.begin()->length(), even if the code runs fine eclipse warns me "Method 'length' could not be resolved".
I tried every possible solution in here: Eclipse CDT C++11/C++0x support without any success. This took me so many hours now, what am I doing wrong?!
Is there anybody getting a project setup without problems with this code?
EDIT: Other code example - same problem:
#include <iostream>
#include <vector>
#include <thread>
using namespace std;
class TestClass {
public:
void test() {
cout << "test" << endl;
}
};
void test() {
vector<TestClass> testClassVector;
TestClass x;
testClassVector.push_back(x);
testClassVector.begin()->test();
}
int main() {
thread(test).join();
return 0;
}
Compiles and runs correct, but returns in eclipse: Method 'test' could not be resolved
EDIT:
working versions:
((TestClass)*(testClassVector.begin())).test();
TestClass foo2 = *(testClassVector.begin());
foo2.test();
still not working:
testClassVector.begin()->test();
The last compiles and works like the two above, but eclipse still claims:
Method 'test' could not be resolved
Maybe I'm wrong, but I think your problem don't come from Eclypse. Juste, begin() on a vector return a std::vector<T>::iterator first, this is not a pointer and there is no method length, but you can ask for the vector size with myvector.size(); if this is what you want.
The problem could come from your #include <string.h> that is not the same as #include <string>, string.h is for string operation like strcmp, strstr, etc... juste string will define the std::string object.
I don't have Eclipse set up but the problem appears to be around std::string. Does the problem go away if you remove the threading from the example? (I also changed to #include <string> instead of string.h)
#include <iostream>
#include <vector>
#include <string>
#include <thread>
using namespace std;
#if 0
void test() {
vector<string> myvector;
string a("Teststring");
myvector.push_back(a);
cout << myvector.begin()->length() << endl;
}
#endif
int main() {
//thread(test).join();
vector<string> myvector;
string a("Teststring");
myvector.push_back(a);
cout << myvector.begin()->length() << endl;
return 0;
}
That should hopefully print out 10.
Update from comment:
Does this generate the Eclipse warning?
auto tmp = *(myvector.begin());
std::cout << tmp.length() << std::endl;
What about this?
std::string foo("abc123");
std::cout << foo.length() << std::endl;
I guess one more too:
std::string foo2 = *(myvector.begin());
std::cout << foo2.length() << std::endl;
The solution found:
I downloaded eclipse kepler Kepler
Created a new project and tried to compile this source code (like above):
#include <iostream>
#include <vector>
#include <thread>
using namespace std;
class TestClass {
public:
void test() {
cout << "test" << endl;
}
};
void test() {
vector<TestClass> testClassVector;
TestClass x;
testClassVector.push_back(x);
testClassVector.begin()->test();
}
int main() {
thread(test).join();
return 0;
}
On the first run eclipse told me, thread belongs to the new c++11 standard and I have to add -std=c++11 to the compiler flags. To use thread I also added -pthread to the linker flags. With this steps the code could be compiled, but eclipse marks the thread still as unknown. To fix this I proceeded the following step:
Under C/C++ Build (at project settings), find the Preprocessor Include Path and go to the Providers Tab. Deselect all except CDT GCC Builtin Compiler Settings. Then untag Share settings entries … . Add the option -std=c++11 to the text box called Command to get compiler specs.
Found here.
Now - unbelievable but true - it works, even without any errors marked by eclipse. The solution is using the (beta) version of eclipse, wich seems to handle this in a better way.
Thanks for all your help!
I was trying to discover some of the goodies of the new C++11 standard (using g++ 4.6.2). Playing around with lambdas in a an "all_of" algorithm function, I encountered a strange problem with the std:: qualifier.
I am "using" the std namespace as shown at the beginning of the code snippet. This makes the declaration of the pair variable in the for loop well-defined.
However, I tried the same in the lambda argument used in the "all_of" algorithm. I came across several hard-to-understand error messages, before I realized that a full std:: qualified std::pair would work there, but only pair not.
Am I missing an important point? The declaration of the lambda happens in this file, so the namespace should still be active here, right? Or does the required std:: qualifier depend on some STL code in a different file? Or is it likely to be a bug in g++?
Best regards,
Peter
PS: the code compiles without warnings as pasted here, but removing the std:: in the all_of lambda, I get an error message.
#include <iostream>
#include <memory>
#include <map>
#include <string>
#include <algorithm>
#include <utility>
using namespace std;
void duckburg() {
const int threshold = 100;
map <string, int> money;
money["donald"] = 200;
money["daisy"] = 400;
money["scrooge"] = 2000000;
// obviously, an "auto" type would work here nicely,
// but this way my problem is illustrated more clearly:
for (const pair <string, int> &pair : money) {
cout << pair.first << "\t" << pair.second << endl;
}
if (all_of(money.begin(), money.end(),
[&](std::pair<string, int> p) {
return bool(p.second > threshold);
}))
{
cout << "yes, everyone is rich!";
} else {
cout << "no, some are poor!";
};
}
Edit: Just noticed I received a downvote for this old question. No problem with that, but please elaborate on the reasons. It will help me improve future questions, and in the end the entire community will profit. Thanks!
Rename the variable pair in your for loop.
It's scope should only extend to the end of the for loop and therefore not interfere with your
lambda, but g++ has some code for ancient for-scoping rules where that was not the case, so it can emit better error messages for ancient C++ code.
It looks as if there is a bug in that compatibility code.
I need to deserialize a std::vector<boost::variant<..>> with decoration supplied by other objects.
One of the things the "decoration" enables is a empty entry in the vector. I have hit a brick wall in my real implementation. However, I have managed to shrink wrap it. Code that compiles :
#include <string>
#include <boost/spirit/include/karma.hpp>
#include <boost/variant.hpp>
#include <boost/cstdint.hpp>
namespace karma = boost::spirit::karma;
typedef boost::variant<boost::int32_t, boost::int64_t> custom_variant;
int main()
{
using karma::generate;
custom_variant v;
std::string temp;
std::back_insert_iterator<std::string> x(temp);
std::cout << v;
karma::generate(x, karma::auto_, v);
}
The offending changes, which attempt to implement a "undefined" type, along with the required concept.
#include <string>
#include <boost/spirit/include/karma.hpp>
#include <boost/variant.hpp>
#include <boost/cstdint.hpp>
namespace karma = boost::spirit::karma;
struct undefined{};
std::ostream & operator<<(std::ostream & out, undefined const & undefined)
{
return out;
}
typedef boost::variant<undefined,boost::int32_t, boost::int64_t> custom_variant;
int main()
{
using karma::generate;
custom_variant v;
std::string temp;
std::back_insert_iterator<std::string> x(temp);
std::cout << v;
karma::generate(x, karma::auto_, v);
}
If I comment out the karma::generate step, std::cout is a valid expression (Boost::variant OutputStreamable). Spirit requires that generators be given types which are OutputStreamable(spirit::karma OutputStreamable) and the variant above should be OutputStreamable since I have made the undefined typeOutputStreamable as a no-op.
What gives ? :(
I'm really beginning to question weather the C++ template mechanism is worth it when using libraries with > 2 levels of template indirection. Perhaps I should go back to straight-c.
Edit 1:
Ok, Clang gave me a sensible first error...
error: no type named 'properties' in 'boost::spirit::karma::no_auto_mapping_exists'
Now I got to figure out how to map undefined as a no-op to get a clean conversion. This spirit documentation entry (and this in specific) describes what I need to look into. Is there a generic undefined type provided by spirit or one defined in boost, that spirit already maps as a no-op ?
Edit 2:
std::vector<boost::optional<boost::variant<..>>> is beginning to look quite appealing since spirit provides type-deduction for them.
I'd suggest to use spirit::unused_type for that purpose as it already is 'known' to Spirit and it has an operator<<() predefined (but any other type will do) - not that you really need that operator for Karma in the first place.
In addition, you have to provide a specialization for create_generator (as you suspected):
namespace boost { namespace spirit { namespace traits
{
template <>
struct create_generator<spirit::unused_type>
{
typedef spirit::karma::eps_type type;
static type call()
{
return spirit::karma::eps;
}
};
}}}
which will map unused_type to karma::eps. This seems to be exactly what you need as eps eats the attribute without generating anything, while succeeding always. If you go this route you will not need to utilize optional<>.