I have difficulty understanding this part of a code? Is it possible to get pictorial/diagram explanation.
//test.h
typedef std::map<std::string, std::string> mType;
static const m_Type::value_type data[] = {
m_Type::value_type("A", "B"),
m_Type::value_type("C", "D"),
m_Type::value_type("E", "F")
};
//test.cc
void test(std::map<std::string, std::string>::value_type data)
{
cout<<data[0].first<<endl;
}
//main.cc
test(data);
In main.cc I wanted to call test() to print elements but getting error
main.cc: In function 'void test(std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >)':
main.cc:10: error: no match for 'operator[]' in 'data[0]'
You have to declare the function the following way
void test( const std::map<std::string, std::string>::value_type data[] )
{
cout<<data[0].first<<endl;
}
because originally data is defined as an array that you are going to pass to the function. Otherwise you may not use the subscript operator.
Also you need to use qualifier const for the parameter because array data also is defined as a constant array.
As for this type
m_Type::value_type
then it is equivalent to std::pair<const std::string, std::string> So this declaration
static const m_Type::value_type data[] = { /*...*/ };
is equivalent to
static const std::pair<const std::string, std::string> data[] = { /*...*/ };
You are supposed to pass to test a value_type not the whole map.
A value_type corresponds to a pair(key, value) and is define like so in stdlib : typedef pair<const Key, Type> value_type;
therefore this data[0]makes no sense. Should be data.first
Related
In the following example, does anyone know why const gets added to the string giving the error below (same with gcc and VS2008)?
#include<utility>
#include<ostream>
#include<string>
#include<map>
class Foo
{
};
class Test
{
public:
Test() { myMap.insert(std::make_pair("a string", Foo())); }
std::pair<std::string, Foo>& GetPair() { return *(myMap.begin()); }
private:
std::map<std::string, Foo> myMap;
};
int main()
{
Test t;
std::pair<std::string, Foo>& myPair = t.GetPair();
return 0;
}
Error:
t.cpp: In member function 'std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Foo>& Test::GetPair()':
Line 14: error: invalid initialization of reference of type 'std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Foo>&' from expression of type 'std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Foo>'
compilation terminated due to -Wfatal-errors.
I don't understand why this would be as I'm not using cbegin(). Also why would the string be const, but not the Foo?
Because if you changed the key part of the pair, then it would suddenly be stored in the wrong location in the map's data structure (bucket, position in tree, or something else depending on the structure). The map doesn't get notified when the key part is changed, so it simply does not allow you to modify it.
On the other hand, the value part is irrelevant to where the pair is stored in the map structure, so you are allowed to change that.
I defined a list of pairs and wish to access them using an iterator, following an example.
class A{
private:
list<pair<size_type,size_type> > l_edge_;
public:
void function() const{
list<pair<size_type,size_type> >::iterator Iter_;
Iter_ = l_edge_.begin();
}
}
However, I got a compilation error. How can I fix it?
error: no match for 'operator=' (operand types are 'const iterator
{aka const std::_List_iterator<std::pair<unsigned int, unsigned int> >}' and
'std::list<std::pair<unsigned int, unsigned int> >::const_iterator
{aka std::_List_const_iterator<std::pair<unsigned int, unsigned int> >}')
My guess is that you are trying to write a const member function, and not what you copied in the question:
void function() const
{
Iter_ = l_edge_.begin();
}
Now, since the function is const, the l_edge_ member is also const, and so, begin() returns a const_iterator instead of a plain iterator. But that hardly matters because the Iter_ member is also const, so it cannot be assigned to.
Usually you do not want to declare iterators as member variables, unless very special needs. Instead, just declare a local one when you need it, and of the appropriate constness:
class A
{
private:
list<pair<size_type,size_type> > l_edge_;
public:
//const member function
void function() const
{
list< pair<size_type,size_type> >::const_iterator iter = l_edge_.begin();
}
//non-const member function
void function()
{
list< pair<size_type,size_type> >::iterator iter = l_edge_.begin();
}
};
I've encountered a strange problem in my C++ Code.
I've defined a TemplateClass called
StateTemplate<T>
Furthermore I defined
typedef StateTemplate<double> StateDouble.
Then I defined a friend function
template<class S>
friend S partialEntangledScalarProduct(
const typename std::vector<StateTemplate<T> >::const_iterator s1,
const typename std::vector<StateTemplate<T> >::const_iterator s2,
const typename std::vector<StateTemplate<T> >::const_iterator sSub1,
const typename std::vector<StateTemplate<T> >::const_iterator sSub2,
vector<unsigned int> const &pos,
vector<unsigned int> const &posNot);
If I now make
std::vector<StateDouble>::const_iterator s1;
std::vector<StateDouble>::const_iterator s2;
std::vector<StateDouble>::const_iterator sSub1;
std::vector<StateDouble>::const_iterator sSub2;
vector<unsigned int> vui;
Doub test=partialEntangledScalarProduct(s1,s2,sSub1,sSub2,vui,vui);
I get the following Error:
no matching function for call to
'partialEntangledScalarProduct(
__gnu_cxx::__normal_iterator<
const StateTemplate<double>*,
std::vector<
StateTemplate<double>,
std::allocator<StateTemplate<double> > > >&,
__gnu_cxx::__normal_iterator<
const StateTemplate<double>*,
std::vector<
StateTemplate<double>,
std::allocator<StateTemplate<double> > > >&,
__gnu_cxx::__normal_iterator<
const StateTemplate<double>*,
std::vector<
StateTemplate<double>,
std::allocator<StateTemplate<double> > > >&,
__gnu_cxx::__normal_iterator<
const StateTemplate<double>*,
std::vector<
StateTemplate<double>,
std::allocator<StateTemplate<double> > > >&,
const std::vector<unsigned int, std::allocator<unsigned int> >&,
std::vector<unsigned int, std::allocator<unsigned int> >&)'
I've tried for hours to find the problem, but it seems that I overlook something.
Maybe someone could help me?
best regards
Dominik
p.s.: if you need more information about my code, just let me know. At the moment I just wanted to give you the important parts.
Here is a small example with the same error.
#include <iostream>
#include <vector>
template<class T>
class StateTemplate{
template<class S>
friend S testFunction(
const typename std::vector<StateTemplate<S> >::const_iterator s1);
public:
StateTemplate();
};
template<class T>
StateTemplate<T>::StateTemplate(){}
template<class T>
T testFunction(
const typename std::vector<StateTemplate<T> >::const_iterator s1)
{
return T(1);
}
int main(){
std::vector<double>::const_iterator s1;
double s=testFunction<double>(s1);
return 0;
}
If you presented the declaration of partialEntangledScalarProduct correctly, the template parameter S isn't used anywhere in the function parameter list. Therefore, the compiler would never deduce it and you have to provide it explicitly.
partialEntangledScalarProduct<SomeClass>(s1,s2,sSub1,sSub2,vui,vui);
SomeClass is just an example, the exact name is unclear unless you provide more details.
(I don't have g++ on this machine, so this is conjecture.)
I think the issue is that the compiler can't deduce S and you're getting an unhelpful error message. Change your usage to the following:
double test = partialEntangledScalarProduct<double>(s1,s2,sSub1,sSub2,vui,vui);
As a side note, make sure your examples compile for you before you post them. I'm assuming Doub was supposed to be double?
That's my first question :)
I'm storing the configuration of my program in a Group->Key->Value form, like the old INIs. I'm storing the information in a pair of structures.
First one, I'm using a std::map with string+ptr for the groups info (the group name in the string key). The second std::map value is a pointer to the sencond structure, a std::list of std::maps, with the finish Key->Value pairs.
The Key->Value pairs structure is created dynamically, so the config structure is:
std::map< std::string , std::list< std::map<std::string,std::string> >* > lv1;
Well, I'm trying to implement two methods to check the existence of data in the internal config. The first one, check the existence of a group in the structure:
bool isConfigLv1(std::string);
bool ConfigManager::isConfigLv1(std::string s) {
return !(lv1.find(s)==lv1.end());
}
The second method, is making me crazy... It check the existence for a key inside a group.
bool isConfigLv2(std::string,std::string);
bool ConfigManager::isConfigLv2(std::string s,std::string d) {
if(!isConfigLv1(s))
return false;
std::map< std::string , std::list< std::map<std::string,std::string> >* >::iterator it;
std::list< std::map<std::string,std::string> >* keyValue;
std::list< std::map<std::string,std::string> >::iterator keyValueIt;
it = lv1.find(s);
keyValue = (*it).second;
for ( keyValueIt = keyValue->begin() ; keyValueIt != keyValue->end() ; keyValueIt++ )
if(!((*keyValueIt).second.find(d)==(*keyValueIt).second.end()))
return true;
return false;
}
I don't understand what is wrong. The compiler says:
ConfigManager.cpp||In member function ‘bool ConfigManager::isConfigLv2(std::string, std::string)’:|
ConfigManager.cpp|(line over return true)|error: ‘class std::map<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >’ has no member named ‘second’|
But it has to have the second member, because it's a map iterator...
Any suggestion about what's happening?
Sorry for my English :P, and consider I'm doing it as a exercise, I know there are a lot of cool configuration managers.
keyValueIt is not a map iterator, it is a list iterator.
You can just do
if (keyValueIt->find(d) != keyValueIt->end())
I think Joel is correct with
if (keyValueIt->find(d) != keyValueIt->end())
However I wanted to encourage you use some typedefs to try and simplify your code. Using typedefs can help when diagnosing problems like this (and if you're lucky your compiler will give you more meaningful error messages as a result.
For instance:
typedef std::map<std::string,std::string> KeyValueMap;
typedef std::list< KeyValueMap > ConfigurationList;
typedef std::map< std::string, ConfigurationList* > ConfigurationMap;
bool isConfigLv2(std::string,std::string);
bool ConfigManager::isConfigLv2(std::string s,std::string d) {
if(!isConfigLv1(s))
return false;
ConfigurationMap::iterator it;
ConfigurationList* keyValue;
ConfigurationList::iterator keyValueIt; // <- it's not a keyValue iterator, it's a ConfigList iterator!
it = lv1.find(s);
keyValue = (*it).second;
for ( keyValueIt = keyValue->begin() ; keyValueIt != keyValue->end() ; keyValueIt++ )
if(!((*keyValueIt).second.find(d)==(*keyValueIt).second.end()))
return true;
return false;
}
Simplifying the types makes it more obvious to me that keyValueIt is probably being misued (i.e. it's actually a list iterator, and not a KeyValueMap iterator and so the '.second' access is erroneous.)
If you just want a group/key/value structure you are over-complicating it, you have one more level in your data structure then needed.
The additional list isn't needed, a map of maps is sufficient:
// typedefs for readability:
typedef std::map<std::string, std::string> Entries;
typedef std::map<std::string, Entries> Groups;
// class member:
Groups m_groups;
bool ConfigManager::hasKey(const std::string& group, const std::string& key)
{
Groups::const_iterator it = m_groups.find(group);
if(it == m_groups.end())
return false;
const Entries& entries = it->second;
return (entries.find(key) != entries.end());
}
I'm using the unordered_map of TR1 implementation in my code and the linker gives weird errors I cannot even decipher:
BPCFG.o: In function `std::__detail::_Hash_code_base<DottedRule, std::pair<DottedRule const, int>, std::_Select1st<std::pair<DottedRule const, int> >, eqDottedRule, std::hash<DottedRule>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, false>::_M_hash_code(DottedRule const&) const':
BPCFG.cpp: (.text._ZNKSt8__detail15_Hash_code_baseI10DottedRuleSt4pairIKS1_iESt10_Select1stIS4_E12eqDottedRuleSt4hashIS1_ENS_18_Mod_range_hashingENS_20_Default_ranged_hashELb0EE12_M_hash_codeERS3_[std::__detail::_Hash_code_base<DottedRule, std::pair<DottedRule const, int>, std::_Select1st<std::pair<DottedRule const, int> >, eqDottedRule, std::hash<DottedRule>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, false>::_M_hash_code(DottedRule const&) const]+0x23): undefined reference to `std::hash<DottedRule>::operator()(DottedRule) const'
BPCFG.o: In function `std::__detail::_Hash_code_base<DottedRule, std::pair<DottedRule const, int>, std::_Select1st<std::pair<DottedRule const, int> >, eqDottedRule, std::hash<DottedRule>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, false>::_M_bucket_index(std::__detail::_Hash_node<std::pair<DottedRule const, int>, false> const*, unsigned long) const':
BPCFG.cpp: (.text._ZNKSt8__detail15_Hash_code_baseI10DottedRuleSt4pairIKS1_iESt10_Select1stIS4_E12eqDottedRuleSt4hashIS1_ENS_18_Mod_range_hashingENS_20_Default_ranged_hashELb0EE15_M_bucket_indexEPKNS_10_Hash_nodeIS4_Lb0EEEm[std::__detail::_Hash_code_base<DottedRule, std::pair<DottedRule const, int>, std::_Select1st<std::pair<DottedRule const, int> >, eqDottedRule, std::hash<DottedRule>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, false>::_M_bucket_index(std::__detail::_Hash_node<std::pair<DottedRule const, int>, false> const*, unsigned long) const]+0x33): undefined reference to `std::hash<DottedRule>::operator()(DottedRule) const'
collect2: ld returned 1 exit status
This is the error and I cannot even detect the line it's oriented from? From the statement:
undefined reference to `std::hash::operator()(DottedRule) const'
I guess that it's about the usage of hash. Now, the whole code is too big (if you nevertheless want to see it I may post it later), but the relevant parts are:
# include <unordered_map> // Used as hash table
# include <stdlib.h>
# include <string.h>
# include <vector>
# define NO_SYMBOL -1
using namespace std;
using std::unordered_map;
using std::hash;
...
...
...
class DottedRule {
public:
int symbol;
int expansion;
int dot_position;
};
struct eqDottedRule
{
bool operator()(const DottedRule & r1, const DottedRule & r2) const
{
return r1.symbol == r2.symbol && r1.expansion == r2.expansion && r1.dot_position == r2.dot_position;
}
};
...
...
...
class BPCFG {
public:
...
...
...
...
unordered_map<DottedRule, int, hash<DottedRule>, eqDottedRule> symbol_after_dot;
...
...
};
The last line I included is the only place where hash is used. Any idea what may be going on?
Thanks a lot,
Onur
From www.sgi.com: "The hash template is only defined for template arguments of type char*, const char*, crope, wrope, and the built-in integral types. If you need a Hash Function with a different argument type, you must either provide your own template specialization or else use a different Hash Function."
I'm pretty sure you need to define a std:size_t hash_value(DottedRule const&) function, and then you'll be able to use hash<DottedRule>. See the boost docs for more info.
Simple hash for my class. It cals hash from string
namespace std
{
template<>
struct hash<Letter> : public __hash_base<size_t, Letter>
{
size_t operator()(const Letter& v) const
{
hash<string> hasher;
return hasher.operator ()(v.getSign());
}
};
}