int CRegister::CountCars(const string& name, const string& surname)const{
const pair<string,string> wholename(name,surname);
vector<CDriver>::iterator Diterator=lower_bound(m_Drivers.begin(),m_Drivers.end(),wholename);
if (Diterator<m_Drivers.end()){
if(Diterator->m_name.compare(wholename.first)!=0 || Diterator->m_surname.compare(wholename.second)!=0) return 0;
return Diterator->m_DriversNumber;
}
return 0;
}
Hello, when I try to compile this, it throws error on the third line:
"conversion from ‘__gnu_cxx::__normal_iterator<const CDriver*, std::vector<CDriver> >’ to non-scalar type ‘std::vector<CDriver>::iterator {aka __gnu_cxx::__normal_iterator<CDriver*, std::vector<CDriver> >}’ requested
When I set the function CountCars as a non-const, it compiles without problems. What should I change to fix this? (the function has to be const)
To solve your problem you have to use a const_iterator
The reason is the following : The method is marked const, which means that the method itself is not going to change state of the object instance upon which the method is invoked.
Therefore within a const method you cannot call any other method on the same object that is not marked const. Because of course that new call does not garantee that it is const so can the first method not claim to be const anymore.
by declaring the iterator const you are going to use the const version of lower_bound.
Try using a const_iterator:
vector<CDriver>::const_iterator Diterator
// ^^^^^^
Consider using a const_iterator, e.g.
vector<CDriver>::const_iterator Diterator
= lower_bound(m_Drivers.begin(), m_Drivers.end(), wholename);
If you can compile in C++11/14, using auto helps as well:
auto Diterator = lower_bound(m_Drivers.begin(), m_Drivers.end(), wholename);
(With auto, the compiler deduces the correct iterator type, without requiring you to correctly "spell" it explicitly in code.)
Related
I'm having trouble with this code:
NonCommutativePolynomial<SR> differential_at_wrt_variable
(std::map<VarId,SR> valuation, VarId variable) {
NonCommutativePolynomial<SR> result;
for(auto &monomial : monomials_) {
result += monomial.first.differential_at_wrt_variable(valuation, variable)
* monomial.second;
}
return result;
}
monomials_ has the type std::map<NonCommutativeMonomial<SR>,std::uint_fast16_t>.
In the line result += ... I'm getting this compiler error:
error: passing ‘const NonCommutativeMonomial’ as ‘this’
argument of ‘NonCommutativeMonomial
NonCommutativeMonomial::differential_at_wrt_variable(std::map&, VarId&) [with SR = LossySemiring]’ discards qualifiers
[-fpermissive]
Now I realize that this means that I am calling a method (function?) on a constant object where the method does not guarantee that it won't modify the object. What I don't understand is how monomial.first can be constant when I haven't declared it to be thus anywhere. Any ideas what I might be doing wrong?
EDIT:
See the answers below why monomial.first is constant. I need a non-constant copy of it, the class NonCommutativeMonomial<SR>has this copy constructor:
NonCommutativeMonomial(const NonCommutativeMonomial &m) = default;
However, when I call that using
NonCommutativeMonomial * mono = new NonCommutativeMonomial<SR>(monomial.first);
and work with mono afterwards, I still get the same error.
In std::map keys are constant objects and you must never change them.
EDIT:
I'd suggest the following change:
NonCommutativePolynomial<SR> result;
for(auto &monomial : monomials_) {
NonCommutativePolynomial<SR> tmp(monomial.first);
result += tmp.differential_at_wrt_variable(valuation, variable)
* monomial.second;
}
it seems that member function differential_at_wrt_variable has no qualifier const while monomial.first is a const object.
Value type is defined for std::map as
typedef pair<const Key, T> value_type;
that is Key has qualifier const.
The value_type of a std::map<KeyType, MappedType> is declared as a std::pair<const KeyType, MappedType>.
An iterator for a std::map (which is what your for loop is using) is over the map's value_type.
In your case this results in monomial.first having the type const NonCommutativeMonomial<SR> which, as you recognise, cannot be used with a non-const member function.
The reason for the key in the value type being const is to prevent the map keys themselves being modified during the iteration.
I can't understand why the following code is wrong.
struct A{
typedef std::vector<std::vector<int>> Base;
// const auto& func(std::size_t e) const
auto func(std::size_t e) const -> decltype(std::declval<Base>()[e])
{
return base[e];
}
Base base;
};
I get compile error with the above snippet in gcc 4.8.1. (error: invalid initialization of reference of type '__gnu_cxx::__alloc_traits > >::value_type& {aka std::vector&}' from expression of type 'const value_type {aka const std::vector}'
return base[e];)
Note that if I delete the const qualifier, it works fine.
But if I replace the part for function signiture by the commented one (to use the automatic type deduction introduced in C++14). No error is generated.
So, I guess the decltype part is wrong.
Since Base is a non-const type, std::declval<Base>()[e] refers to a non-const version of operator[] of std::vector. That version of [] returns a non-const reference of type std::vector<int> &. So, the return type of your function is declared as decltype(std::declval<Base>()[e]), which is std::vector<int> &.
Meanwhile, your member function func is declared as const. It means that member base will have const Base type inside that member function. This in turn means that the application of operator [] to base will refer to const version of operator []. That version of [] returns the result of const vector<int> & type.
So, your return statement attempts to implicitly convert a const vector<int> & value to a vector<int> & value. This conversion is invalid. It violated the rules of const-correctness.
Either add const in the return type, as #catscradle suggested. Or remove const from method declaration
auto func(std::size_t e) -> decltype(std::declval<Base>()[e])
Either this or that.
This works:
auto func(std::size_t e) const -> decltype(std::declval<const Base>()[e])
I faced a compilation problem that I do not understand, I have simplified it a bit for explanation below.
Basically, it involves having 2 different getters (a const and non-const one) that return a container (a map in this example) with const, respectively non-const value_type.
What puzzles me is that in the example below, the compiler seems unable to use the const getter on a non-const object:
#include "stdafx.h"
#include <utility>
#include <map>
class TestObject
{
public:
TestObject() {}
virtual ~TestObject() {}
};
typedef std::pair<const TestObject*, const TestObject*> ConstTestObjectPair;
typedef std::pair<TestObject*, TestObject*> TestObjectPair;
class Test
{
TestObject* m_pObject;
public:
Test() {m_pObject = new TestObject();}
virtual ~Test() {delete m_pObject;}
std::map<unsigned, ConstTestObjectPair> GetObject() const
{
std::map<unsigned, ConstTestObjectPair> map;
map.insert(std::make_pair(0, std::make_pair(m_pObject, m_pObject)));
return map;
}
std::map<unsigned, TestObjectPair> GetObject()
{
std::map<unsigned, TestObjectPair> map;
map.insert(std::make_pair(0, std::make_pair(m_pObject, m_pObject)));
return map;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
Test* pTest = new Test();
const Test* pConstTest = pTest;
std::map<unsigned, ConstTestObjectPair> CTO = pTest->GetObject(); // Not compiling, I don't get why!!!
CTO = pConstTest->GetObject();
std::map<unsigned, TestObjectPair> TO = pTest->GetObject();
//TO = pConstTest->GetObject(); // Not working, this is expected
return 0;
}
I tried with both VS2010 and gcc and neither accepts to compile this code. Here is the compilation error returned by VS2010:
1>c:\test.cpp(48): error C2440: 'initializing' : cannot convert from 'std::map<_Kty,_Ty>' to 'std::map<_Kty,_Ty>'
1> with
1> [
1> _Kty=unsigned int,
1> _Ty=TestObjectPair
1> ]
1> and
1> [
1> _Kty=unsigned int,
1> _Ty=ConstTestObjectPair
1> ]
1> No constructor could take the source type, or constructor overload resolution was ambiguous
Could someone explain me why the compiler cannot find/use the correct prototype on the non-const object?
Thanks a lot!
If you're really curious, check out section 13.3.3 of the C++03 standard, which describes how the "best viable function" is determined. Here are some important points:
The selection criteria for the best function are the number of arguments, how well the arguments
match the types of the parameters of the candidate function, how well (for nonstatic member functions) the
object matches the implied object parameter, and certain other properties of the candidate function. [Note:
the function selected by overload resolution is not guaranteed to be appropriate for the context. Other
restrictions, such as the accessibility of the function, can make its use in the calling context ill-formed. ]
And later:
If there is exactly one viable function that is a better function than all other viable functions, then it is the
one selected by overload resolution
Note that the return type of the function is not mentioned in this criteria. So the non-const method is selected as most valid, because its "implied object parameter" (essentially the "this" pointer) is non-const. This all happens before the conflict with the return type is detected.
To solve this problem, I would either:
Change your design so that ConstTestObjectPair isn't needed, and you can just use const TestObjectPair (preferred solution)
Cast your non-const objects to const ones when needed
What puzzles me is that in the example below, the compiler seems unable to use the const getter on a non-const object
It is not "unable" but required to chose the other one.
Overloading is selected using the passed actual parameters. For member function including the hidden param used for this. For T* the non-const overload is selected, if you want the other you must use a const T* by cast or other means.
Actually it is a common mistake to think the return type will be used some way and the function that returns what you want to use in the expression gets selected. It is just not so.
The problem is quite simple. pTest is a pointer to an object of type Test, which is not const. Hence in the call pTest->GetObject() the non-const member function is selected, that is
std::map<unsigned, TestObjectPair> GetObject()
As you see, this function returns a value of type std::map<unsigned, TestObjectPair>. But then you try to initialize the variable CTO of type
std::map<unsigned, ConstTestObjectPair>
with this value. To do that, the compiler needs to convert the returned value to this type. But there is no conversion constructor to do that. And that is what the compiler error tells you.
C++ compiler will choose the explicit overrided method, so here pTest is a non-const viable and pConstTest is const one.
Test* pTest = new Test();
const Test* pConstTest = pTest;
pTest->GetObject will choose the non-const GetObject:
std::map<unsigned, TestObjectPair> GetObject()
{
std::map<unsigned, TestObjectPair> map;
map.insert(std::make_pair(0, std::make_pair(m_pObject, m_pObject)));
return map;
}
pConstTest->GetObject() will choose the const GetObject:
std::map<unsigned, ConstTestObjectPair> GetObject() const
{
std::map<unsigned, ConstTestObjectPair> map;
map.insert(std::make_pair(0, std::make_pair(m_pObject, m_pObject)));
return map;
}
the first error happened when you assign a returned
std::map<unsigned, TestObjectPair> value
to a
std::map<unsigned, ConstTestObjectPair> viable
I have a problem providing the correct overloading for const and not const getter functions with the new return value syntax.
In my class PhysicalNode I have defined a getter function with the new return value syntax. This is needed as the return type of the getter depends on the type of the member.
class PhysicalNode {
private:
solver::EnergySolver energySolver_; ///< The energy solver of this node
//solver::EnergyMomentumSolver energySolver_
public:
auto getEnergySolver()-> typename
std::add_lvalue_reference<decltype(PhysicalNode::energySolver_)>::type;
}
However I want now to also provide this method as const.
Normally I would use function overloading to define my const and not const getter function like that.
class PhysicalNode {
private:
solver::EnergySolver energySolver_;
public:
const solver::EnergySolver& getEnergySolver() const;
solver::EnergySolver& getEnergySolver();
}
I have tried the following function declaration but it does not work:
const auto getEnergySolver() const-> typename
std::add_lvalue_reference<decltype(PhysicalNode::energySolver_)>::type;
The compile error is:
PhysicalNode.cpp:72: error: invalid initialization of reference of type
'std::__add_lvalue_reference_helper<LbmLib::solver::EnergySolver, true,
false>::type {aka LbmLib::solver::EnergySolver&}' from expression of type
'const LbmLib::solver::EnergySolver'
How do I need to define the function declaration to define this function as constant.
If you really really want to use this notation and the standard type traits, you should write your const overload this way:
auto getEnergySolver() const ->
std::add_lvalue_reference<
std::add_const<decltype(PhysicalNode::energySolver_)>::type
// ^^^^^^^^^^^^^^
>::type;
Otherwise you would be returning a reference to non-const, which is clearly wrong considering your member function is const-qualified.
Notice, however, that type traits are not really needed here (if EnergySolver is just a regular type and not a reference type alias):
auto getEnergySolver()-> decltype(PhysicalNode::energySolver_)&;
auto getEnergySolver() const -> decltype(PhysicalNode::energySolver_) const&;
But even decltype is unnecessary. If your real program is not more complicated than the example you are showing, this is enough:
auto getEnergySolver()-> solver::EnergySolver&;
auto getEnergySolver() const -> solver::EnergySolver const&;
It's unclear why the "traditional" method is not good for your purposes.
The machination with decltype and add/remove trickery is to cover ground for templates that want to be overly generic. Where you must deal with unknown types and ones you have no control over.
For the usual situations it is way clearer to just add a few typedefs and use those directly.
For your attempt, IMO you use it incorrectly, either try const auto& in front, or auto in front and assemble the type all the way after the ->, combininge remove_reference, then add_const then add_lvalue_reference, it may work, though would make head spin.
decltype(PhysicalNode::energySolver_) is plain EnergySolver, not const EnergySolver even though the method is const, since the expression doesn't use this, which is what that const qualifier really affects. And you're not allowed to use decltype(this->energySolver_) in this context since PhysicalNode is not yet complete.
You'll have to do something like -> const decltype(PhysicalNode::energySolver_)&; or -> std::add_lvalue_reference<std::add_const<decltype(PhysicalNode::energySolver_)>::type>::type; or something in between.
I'm having some trouble with a particular piece of code, if anyone can enlighten me on this matter it would be greatly appreciated, I've isolated the problem down in the following sample:
#include <iostream>
using namespace std;
class testing{
int test();
int test1(const testing& test2);
};
int testing::test(){
return 1;
}
int testing::test1(const testing& test2){
test2.test();
return 1;
}
So what could possibly have cause the following error:
test.cpp:15: error: passing ‘const testing’ as ‘this’ argument of ‘int testing::test()’ discards qualifiers
Thanks a lot!
The problem is calling a non-const function test2.test() on a const object test2 from testing::test1.
testing::test1 gets test2 as a parameter const testing &test2. So within testing::test1, test2const. Then in the first line of the function:
test2.test()
The testing::test function is called on test2. That function is not declared with const at the signature end, so it may modify the object it is called on (the this pointer implicitly passed to it), and even though it does not, the compiler assumes so. By letting you call it there, the compiler would let you modify a const variable without an explicit cast, which C++ is not supposed to allow. Therefore to explain the error message:
test.cpp:15: error: passing ‘const testing’ as ‘this’ argument of ‘int testing::test()’ discards qualifiers
this refers to the object the member function (testing::test) operates on, and in this case it is not const, because testing::test was not declared with const, and thus the mismatch is detected when trying to make a non-const pointer (this) refer to a const object (testing), ignoring the const qualifier.
To solve this, decide whether the testing::test function should ever need to modify the object it is called on (the way it is written now it does not, as all it does is return 1, however that may change, so you need to think at what its intended functionality is). If it should, then obviously calling it on a const object is bad, although you can use const_cast to ask the compiler to override that, but this is dangerous. If it should not, then mark it const, so that it can be called on const objects as well:
class testing{
int test1() const;
// ...
}
int testing::test() const {
// ...
}
Because of the definition of the member function test1:
int testing::test1(const testing& test2){
test2.test();
return 1;
}
You are passing in a const reference of for the variable test2.
That means that you cannot modify any member of test2 and you cannot call any member function that is not const or is not static.
Here is how you can fix:
int testing::test() const {
return 1;
}
The extra const at the end tells the compiler that you are not planning on modifying the content of the current object (and if you do you will get a different compiling error).
The line:
test2.test()
is calling a non const function, even though test2 is a const reference. That's the problem. You can fix this by making testing::test a const function.
testing::test1(const testing& test2) is expecting the passed object to be const, and it will give you an error if you either modify the values of it's variables, or access any methods thereof that are not explicitly defined as const.
Since the test() method doesn't actually change any data, best practice is to set it const, as follows:
class testing{
int test() const;
int test1(const testing& test2);
};
int testing::test() const {
return 1;
}
Alternatively, just remove the word const when defining the arguments for test1(), and it will allow you to access any of the passed object's methods at your leisure.
For a quick and dirt solution, try compiling with -fpermissive as often suggested by the compiler itself (which is probably what VisualStudio compilers do, being that Windows users seldom report this problem).