I have the following code:
typedef bool (A::*rule)(shared_ptr<Node >, shared_ptr<Node> ) ;
when initilaising the class A object, I run the following code
v_ = vector<rule>();
v_.push_back(A::memberFunction);
I have also tried with v_.push_back(&A::memberFunction) as this seemed more logical to me, but was
advised against on the forums. I also get an error message
This is as suggested by the many topics on the matter. However, I get the following error
non-const lvalue reference to type 'value_type' (aka 'bool (boost::shared_ptr<Node>, boost::shared_ptr<Node>)')
cannot bind to a temporary of type '<bound member function type>'
Does anyone know where I am going wrong?
I have also tried with v_.push_back(&A::memberFunction) as this seemed more logical to me, but was advised against on the forums.
I don't know what forums were those. Forming a pointer-to-member has a single valid syntax, and it is & classname::membername. All elements mandatory.
Use that consistently and post code and error message for that version should the problem persist.
This code compiles under llvm/clang 4.2 (As #balog-pal said, the & is mandatory before classname::membername:
#include <memory>
#include <vector>
struct Node {};
struct A
{
bool rule(std::shared_ptr<Node>, std::shared_ptr<Node>)
{return true;}
};
typedef bool (A::*rule)(std::shared_ptr<Node>, std::shared_ptr<Node> );
int main(int, const char**)
{
std::vector<rule> v;
v.push_back(&A::rule);
return 0;
}
Please post a full not-compiling example, your issue must be hidden somewhere else.
Related
I have the following code
#include <boost/function.hpp>
#include <boost/bind.hpp>
class Foo {
public:
int getIfoo();
};
int Foo::getIfoo() {
return 5;
}
int main () {
boost::function<int (Foo)> getIntFoo;
getIntFoo = boost::bind( &Foo::getIfoo, _1 );
return 0;
}
When I compile with the following command g++ TestBoostBind.cpp I've got the following error
/includes/boost_1_60_0/boost/bind/mem_fn_template.hpp:35:36: error: invalid conversion from ‘const Foo*’ to ‘Foo*’ [-fpermissive]
BOOST_MEM_FN_RETURN (u.*f_)();
~~~~~~~^~
I'm confused about the source of the error whether it's originally from my code or the boost library. Does anyone know what the error means and how to fix it? I use g++ (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0 and boost.1.60
When binding to a member function, the first argument needs to be a pointer or a reference to the object to call the function on. It specifically can't be a value (an actual object instance). The boost::bind function have special cases for these two alternatives to generate the correct objects. It does not have any special case for passing by value.
Therefore you need to define getIntFoo as a function taking a pointer to Foo:
boost::function<int (Foo*)> getIntFoo;
Or a reference:
boost::function<int (Foo&)> getIntFoo;
You could try to use std::mem_fn to achieve the same goal:
Foo f;
std::function<int(Foo &)> getIntFoo = std::mem_fn(&Foo::getIfoo);
int ret = getIntFoo(f);
or if you need pointer argument, std::function could resolve this for you:
Foo f;
std::function<int(Foo *)> getIntFoo = std::mem_fn(&Foo::getIfoo);
int ret = getIntFoo(&f);
boost have its own alternative
I'm attempting to build a large project that has many dependencies. The last thing (?) preventing it from building is TBB's failure to handle casting of an int into an const tbb::<unsigned int>&. The annoying thing is that the same cast using std::atomic (specifically const std::atomic<unsigned int>&) works just fine. I can't refactor the code to use std instead of tbb (it uses other features of tbb that aren't part of std).
I've created the following simple test case:
#include <tbb/atomic.h>
#include <atomic>
void good(const std::atomic<unsigned int>& i) {
}
void bad(const tbb::atomic<unsigned int>& i) {
}
int main() {
good(1);
bad(1); // error C2664: 'void bad(const tbb::atomic<unsigned int> &)': cannot convert argument 1 from 'int' to 'const tbb::atomic<unsigned int> &'
}
Does anyone know how to fix this (without removing use of TBB)? I need it to work in VS2017.
Edit:
Also, I get the following error:
Error (active) E0415 no suitable constructor exists to convert from "int" to "tbb::atomic<unsigned int>" Testmain.cpp 15. So presumably, if there were a suitable c'tor, the cast would succeed. How can I add one? Is there an edit to tbb/atomic.h that would enable this cast?
Fixed! The problem was with the pre-processor defines being out of date for the NuGet distro of TBB I was using. VS2017 version 15.3.2 has support for constexpr, which is needed to enable __TBB__ATOMIC_CTORS. Thanks to #StoryTeller for pointing me in the right direction.
Fix: Git clone latest src of TBB and build. (Funny how shortcuts in C++ rarely are shortcuts).
From the sources (which I found at https://github.com/01org/tbb/blob/tbb_2017/include/tbb/atomic.h, I don't have TBB myself) I can see that struct atomic only has an assignment operator defined, so no non-explicit constructor, which means that you have to explicitly construct it with tbb::make_atomic.
I have this really simple line of code in my production-code(A.cpp) as follows:
std::string A::getString(int i) {
return sVect_[i];
}
with the header as follows:
class A{
public:
std::string getString(int i);
...
private:
vector<std::string> sVect_;
...
};
I've been trying to test the getString() function using googletest but an error keeps popping out:
error: invalid conversion from 'char* (*)(const char*, int)throw ()' to 'int'
error: initializing argument 1 of 'std::string A::getString(i)'
This was my test program:
TEST(ATest, getString){
A a;
EXPECT_EQ("c", a.getString(i));
}
I couldn't quite grasp the workaround of the vector string and how to call it in my test program without ever changing the production code. I even use the hack, adding #define statements, to access the private member but still couldn't do it.
How do my test actually looks like to successfully call that function?
Note: I'm on Linux and using gcc. Thank you in advance guys.
Perhaps the error message is misleading. Have you defined i globally somewhere else? To me it looks like in the local scope because it does not know what the value of the variable i is, it is misbehaving in an unexpected way
TEST(ATest, getString){
A a;
EXPECT_EQ("c", a.getString(i)); //here what is the 'i' and where is it defined
}
I'm trying to update a old project that has been building with visual studio 2005 to uses visual studio 2012, and I'm getting an error that I cant solve.
The code that works fine under VS2005:
#include <iostream>
#include <string>
#include <sstream>
using std::cout;
using std::wcout;
using std::endl;
using std::wstring;
using std::string;
class Value
{
public:
Value(const wstring& value)
{
v = value;
}
Value(Value& other)
{
this->v = other.v;
}
template<typename T>
operator T() const
{
T reply;
std::wistringstream is;
is.str(v);
is >> reply;
return reply;
}
operator wstring() const
{
return v;
}
private:
wstring v;
};
int main()
{
Value v(L"Hello World");
wstring str = v;
wcout << str << endl;
Value int_val(L"1");
int i = int_val;
cout << i + 1 << endl;
return 0;
}
When I'm compiling this under VS2012 I get an error on the line "wstring str = v;", the error is:
error C2440: 'initializing' : cannot convert from 'Value' to 'std::basic_string<_Elem,_Traits,_Alloc>'
1> with
1> [
1> _Elem=wchar_t,
1> _Traits=std::char_traits<wchar_t>,
1> _Alloc=std::allocator<wchar_t>
1> ]
1> No constructor could take the source type, or constructor overload resolution was ambiguous
I can kinda fix it by changing the operator signature from 'operator wstring() const' to 'operator const wstring&() const'. But why does the original code not work, even though it works in VS2005.
I'm not getting an error on the line "int i = int_val;".
This also compiles and runs fine with GCC (g++) in cygwin (version 4.5.3).
Update
To really simulate my real problem there was some information left out in the sample code above. In between the Value class and the usage is a few other classes. One that look like this:
class Config
{
public:
virtual Value getValue(const string& key) const = 0;
Value operator()(const string& key)
{
return getValue(key);
}
};
And the usage
const wstring value2 = config("key");
That will give the error above when compiling but also IntelliSense will give other hints on whats wrong and it says: "More than one user-defined conversion from "Value" to "const std::wstring" applies:" and it points at both the regular constructor and the move constructor of basic_string. So it seem to have something to do with rvalues to do and I have been reading up on that, and understand the basics. But there is probably a lot I am missing.
I find that I can fix this problem by changing the usage to:
const wstring&& value = config("key");
Then it seem like the VS2012 compiler understand which constructor it should use then.
Questions:
* Are there a way to not use && in this example?
* What is really happening here?
I put up the sample code on GitHub:
https://github.com/Discordia/ImplicitTypeConversion
In simple (hopefully not simplified) terms, with C++11, you'll have to start thinking of references in terms of lvalue and rvalue. Basically, C++11 gives you the ability to handle operations on references differently depending on whether or not you are dealing with a "temporary" object. This gives you ability to do things like move data internal to your object rather than copy in different situations. The down side to this is the effect you are seeing, where old code is not specific enough about which you are dealing with. There's more to it than that, it's not really something that can be fully explained in a short SO answer, but previous answers gave some good places to start. I would rework your code to provide both rvalue and lvalue operators (which it sounds like you're already on your way to doing).
I am a avid emacs user, and want to use sgml markup check routine.
I was naturally headed towards nsgmls, and downloded the source code to compile it.
However, there was a strange error coming from the compiler with the followings.
./../include/RangeMap.h:57: error: type ‘Vector<RangeMapRange<From, To> >’ is not deri ved from type ‘RangeMapIter<From, To>’
./../include/RangeMap.h:57: error: expected ‘;’ before ‘ptr_’
./../include/RangeMap.h: In member function ‘Boolean RangeMapIter<From, To>::next(From&, From&, To&)’:
./../include/RangeMap.h:47: error: ‘ptr_’ was not declared in this scope
I know that some times compiler gets disgruntled by template and typename madness, however the codes seems to have already used typename correctly within the code.
Here are the cope snippets that arouses these errors.
template<class From, class To>
class RangeMapIter {
public:
RangeMapIter(const RangeMap<From,To> &map);
Boolean next(From &fromMin, From &fromMax, To &toMin) {
if (!count_)
return 0;
else {
fromMin = ptr_->fromMin;
fromMax = ptr_->fromMax;
toMin = ptr_->toMin;
ptr_++;
count_--;
return 1;
}
}
private:
size_t count_;
typename Vector<RangeMapRange<From,To> >::const_iterator ptr_;
};
Can anybody help me hash out those errors?
This error message is given by GCC in the wrong order of both type names. (but it apparently fixed this in the latest version). It is meant to say that Vector<RangeMapRange<From,To> >::const_iterator was not found to be a type name. The underlying cause of this diagnostic is that the code is parsed as an access-declaration, which has the following syntax
::[opt] nested-name-specifier template[opt] unqualified-id ;
An example of that syntax
struct A {
int a;
};
struct B : A {
// equivalent to: using A::a;
A::a;
};
In C++11 this access-declaration construct was taken out of the specification and it was deprecated in C++03. But since the compiler still supports parsing it, when the Vector<RangeMapRange<From,To> >::const_iterator is not found to be a type, it will be taken as a name to be declared in an access-declaration (so the parser moves forward across the type specifier section). Hence according to the above syntax, after the unqualified-id which in this case is const_iterator (and in my example was a), it wants to see a semicolon and it wants that Vector<RangeMapRange<From, To> > is a base class of RangeMapIter<From, To>, but confusingly the diagnostic it gives has it the other way around.
Check your names and make sure the type exists.