Problem
I want to assign values in a class definition which is in a separate header file from the class declaration cpp.
On compilation I recieve theses error messages:
error: ‘const std::map<unsigned int, std::basic_string<char> > bob::mRegexes’ is not a static member of ‘class bob’const std::map<uint,std::string> bob::mRegexes = {
^
error: ‘const std::map<unsigned int, std::basic_string<char> > bob::mResponses’ is not a static member of ‘class bob’ const std::map<uint,std::string> bob::mResponses = {
both of which have been absolutely infurriating because I do not understand why the compiler is ignoring thetypedef for std::string I feel like I'm missing something here but I'm not sure why the bob.h file is seeing the parameters differently than the bob.cpp.
bob.h
#ifndef BOB_H
#define BOB_H
#include <iostream>
#include <string>
#include <boost/regex.hpp>
#include <map>
typedef unsigned int uint;
// This was first to go when I started having problems.
/*using std::string;*/
using std::map;
// boost::regex > c++11::regex (gcc doesn't follow standards).
using boost::regex;
class bob
{
enum respond_to{
QUESTION,
YELL,
NAME,
DEFAULT,
LENGTH
};
public:
static const respond_to mResponseTypes;
static const map<uint,std::string> mRegexes;
static const map<uint,std::string> mResponses;
static std::string hey(std::string sentence);
static const std::string* evaluate (const std::string& sentence);
static const std::string* getResponse(const std::string& sentence, const respond_to& type) noexcept(true);
};
#endif
bob.cpp
#include "bob.h"
const std::map<uint,std::string> bob::mRegexes = {
{QUESTION, "[a-z]+\\?"},
{YELL,"[A-Z]+"}
};
const std::map<uint,std::string> bob::mResponses = {
{QUESTION,"Sure"},
{YELL,"Whoah, chill out!"},
{DEFAULT,"Whatever."}
};
// ...
Related
abstract base class:
#ifndef BUILDINGORG_H
#define BUILDINGORG_H
#include <iostream>
#include <memory>
#include <vector>
class BuildingOrg
{
public:
BuildingOrg(int _id);
virtual int addBuildingComponent(std::shared_ptr<BuildingOrg> buildingOrg,
std::string _type) const;
virtual void removeBuildingComponent(std::shared_ptr<BuildingOrg> buildingOrg);
virtual void getInfo()=0;
private:
int id;
std::string type;
};
#endif // BUILDINGORG_H
concrete subclass:
#ifndef BUILDINGCOMPONENT_H
#define BUILDINGCOMPONENT_H
#include "buildingorg.h"
class BuildingComponent : public BuildingOrg
{
public:
BuildingComponent(int _id);
int addBuildingComponent(std::shared_ptr<BuildingOrg> _buildingOrg,
std::string _type) const override;
void removeBuildingComponent(std::shared_ptr<BuildingOrg> buildingOrg)
override;
void getInfo() override;
private:
std::vector<std::shared_ptr<BuildingOrg>> building_Org;
};
#endif // BUILDINGCOMPONENT_H
Implementation of subclass:
#include "buildingcomponent.h"
BuildingComponent::BuildingComponent(int _id):
BuildingOrg(_id)
{
}
int BuildingComponent::addBuildingComponent(std::shared_ptr<BuildingOrg> _buildingOrg, std::string _type) const
{
building_Org.push_back(_buildingOrg);// I am having error here
return 1;
}
void BuildingComponent::removeBuildingComponent(std::shared_ptr<BuildingOrg> buildingOrg)
{
}
void BuildingComponent::getInfo()
{
}
When I try to put shared pointer in my Vector I get this nasty error;
I really don't know why I am getting the error:
cpp:10: error: passing 'const std::vector<std::shared_ptr<BuildingOrg> >' as 'this' argument of 'void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = std::shared_ptr<BuildingOrg>; _Alloc = std::allocator<std::shared_ptr<BuildingOrg> >; std::vector<_Tp, _Alloc>::value_type = std::shared_ptr<BuildingOrg>]' discards qualifiers [-fpermissive]
building_Org.push_back(_buildingOrg);
I don’t understand what is it saying.
The const in int addBuildingComponent(std::shared_ptr<BuildingOrg> _buildingOrg, std::string _type) const override; is a promise that addBuildingComponent will not change BuildingComponent. However, it tries to modify the member variable building_Org with the push_back()...
Removing the const from addBuildingComponent() should fix the error.
The discards qualifiers part of the error message refers to the conflict with the const qualifier of the member function.
C++ template related error messages can be notoriously difficult to parse at first, but it does get easier with practice :-)
You defined BuildingComponent::addBuildingComponent method as const (i.e. that it won't change member varialbles), but you are adding passed in value to a member list (i.e. changing the member variable).
addBuildingComponent() is a const method. within its scope, *this is const, and so this->building_Org is const.
std::vector::push_back() is a non-const method. So it can't be called in a context where the vector is const.
I am playing around with an ORM design using gcc 4.9.2. I have a class of 2 members:
class Staff : public Db::TableBase<Staff> {
public:
long int staffId_;
std::string nickname_;
}
(TableBase is a class I use to pull in several static functions and subclass declarations into class scope. It has no members or methods, only static functions and subclass declarations.)
I have have a ColumnObject for each member:
static constexpr auto colTest1=Db::detail::ColumnObject<Staff,long int>
(&Staff::staffId_,"staff_id",Db::BigSerial | Db::Default,Db::Transport::TEXT);
static constexpr auto colTest2=Db::detail::ColumnObject<Staff, std::basic_string<char> >
(&Staff::nickname_,"nick_name",Db::NotNull,Db::Transport::TEXT);
The first statement compiles, the second does not:
~/git/WebSchedule2/src/common/ORM/Staff.hpp:110:152: error: ‘const Db::detail::ColumnObject<Staff, std::basic_string<char> >{&Staff::nickname_, ((const char*)"nick_name"), 1, (Db::Transport)0, -1}’ is not a constant expression
static constexpr auto colTest2=Db::detail::ColumnObject<Staff, std::basic_string<char> >(&Staff::nickname_,"nick_name",Db::NotNull,Db::Transport::TEXT);
You might say that the reason the second statement doesn't compile is because the type dependency on std::string makes it a non-literal. However, I don't actually use a string in the definition of ColumnObject, I only use the type information.The definition of ColumnObject:
template<typename Derived,typename MemberType>
class ColumnObject {
public:
MemberType Derived::*memberPtr_;
char const *columnName_;
int const traits_;
Db::Transport transport_;
int columnNumber_;
constexpr ColumnObject()
: memberPtr_(nullptr), columnName_("UNITIALIZED COLUMN"), traits_(-1),
transport_(Db::Transport::TEXT), columnNumber_(-1) { }
constexpr ColumnObject(MemberType Derived::*memberPtr, char const *columnName,
int const traits, Db::Transport transport)
: memberPtr_(memberPtr), columnName_(columnName), traits_(traits),
transport_(transport), columnNumber_(-1) { }
}
Any ideas how I can work around this?
(Edit: I am including a complete example below. The problem seems to be using static constexprs.)
// g++ -Wall -Wextra -pedantic -std=c++14 -c foo.cpp
#include <string>
template<typename Derived,typename MemberType>
class ColumnObject;
template<typename Derived,typename MemberType>
class ColumnObject {
public:
MemberType Derived::*memberPtr_;
char const *columnName_;
constexpr ColumnObject()
: memberPtr_(nullptr), columnName_("UNITIALIZED COLUMN") { }
constexpr ColumnObject(MemberType Derived::*memberPtr, const char *columnName)
: memberPtr_(memberPtr), columnName_(columnName) { }
};
class Staff {
public:
long int staffId_;
std::string nickname_;
Staff(){
staffId_=0;
nickname_="";
}
Staff(long int snid, std::string nname)
: staffId_(snid), nickname_(nname)
{
};
static constexpr auto colTest1=ColumnObject<Staff,long int>(&Staff::staffId_,"staff_id");
static constexpr auto colTest2=ColumnObject<Staff, std::string >(&Staff::nickname_,"nick_name");
};
int main(int argc, char *argv[]){
constexpr auto colTest3=ColumnObject<Staff,long int>(&Staff::staffId_,"staff_id");
constexpr auto colTest4=ColumnObject<Staff, std::string >(&Staff::nickname_,"nick_name");
}
working fine here, on clang :) -> coliru.stacked-crooked.com/a/b9a3102e4849b0d0 – pepper_chico
This now works in RedHat gcc 5.3.1-2. – user2352497
I have a class, and within that class I define a struct. The struct has overloaded comparison operators so that it can be used with a map (with an int as the key).
Prior to messing with classes, I had the struct defined in a .cc file, and that file also contained a function which returned a map of this struct. It worked.
Now I want to have the struct defined in the class header, and the class should have a function which returns a map of structs.
Here is a simplified version of my code, which compiles with the same error as the full version. I don't understand the error, and would appreciate any help!
Cheers.
myclass.h:
#include <map>
class myclass {
public:
struct mystruct {
int i;
mystruct();
mystruct(int j);
bool operator==(const mystruct& rhs);
bool operator>(const mystruct& rhs);
bool operator<(const mystruct& rhs);
};
::std::map<int,mystruct> getStructMap();
};
myclass.cc:
#include <map>
#include "myclass.h"
myclass::mystruct::mystruct(int j) : i(j) {};
myclass::mystruct::mystruct() : i(-1) {};
bool ::myclass::mystruct::operator==(const ::myclass::mystruct& rhs) {return i==rhs.i; }
bool ::myclass::mystruct::operator>(const ::myclass::mystruct& rhs) {return i>rhs.i; }
bool ::myclass::mystruct::operator<(const ::myclass::mystruct& rhs) {return i<rhs.i; }
::std::map<int,::myclass::mystruct> ::myclass::getStructMap() {
::std::map<int,::myclass::mystruct> structMap;
for (int i=0;i<5;i++) structMap[i]=::myclass::mystruct(i);
return structMap;
}
myprogram.cc:
#include <iostream>
#include <map>
#include "myclass.h"
int main() {
myclass myobj;
::std::map<int,::myclass::mystruct> mymap;
mymap=myobj.getStructMap();
}
compile error:
> g++ -o myprogram myprogram.cc myclass.cc
myclass.cc:12: error: ‘class std::map<int, myclass::mystruct, std::less<int>,std::allocator<std::pair<const int, myclass::mystruct> > >::myclass’ has not been declared
myclass.cc:12: error: ISO C++ forbids declaration of ‘getStructMap’ with no type
myclass.cc: In function ‘int getStructMap()’:
myclass.cc:15: error: cannot convert ‘std::map<int, myclass::mystruct, std::less<int>, std::allocator<std::pair<const int, myclass::mystruct> > >’ to ‘int’ in return
Currently your code in parsed as
/*missing type*/ ::std::map<int,::myclass::mystruct>::myclass::getStructMap()
Thus, first error, map doesn't have myclass member (or subclasses, method, typedef, ...)
then the second error : no return type (so assuming int and thus the conversion error).
So to solve that, in myclass.cc, you may remove extra :: as follow:
::std::map<int,::myclass::mystruct> myclass::getStructMap() {
or add extra parenthesis:
::std::map<int,::myclass::mystruct> (::myclass::getStructMap()) {
I compiled the below code with gcc4.4.1 on linux:-
#include "glob.h"
#include "netlist.h"
#include "netlist_params.h"
#include "netlist_abbrev.h"
#include "lvs_util.h"
#include "lvs_report.h"
#include "lvs_data.h"
#include "compare_opts.h"
#include "flatten.h"
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <math.h>
#include "hash.h"
static THREAD_PRIVATE NlStringVec* ext_str_tab_v;
static THREAD_PRIVATE const char* ext_str_tab_s1;
static THREAD_PRIVATE const char* ext_str_tab_s2;
int Netlist::ExtStrHash::operator () (NlString i) const {
if (i.is_valid())
ext_str_tab_s1 = (*ext_str_tab_v)[i];
return Hash<const char*>::operator()(ext_str_tab_s1);
}
Error:-
netlist_back_1.C: In member function 'int Netlist::ExtStrHash::operator()(NlString) const':
netlist_back_1.C:24: error: expected primary-expression before '<' token
netlist_back_1.C:24: error: expected primary-expression before 'const'
netlist_back_1.C:24: error: expected ';' before 'const'
netlist_back_1.C:24: error: expected unqualified-id before '>' token
netlist_back_1.C:24: error: expected initializer before '>' token
Definition of hash in file hash.h:-
namespace Hash {
// template <class Key> struct Hash { };
#define DECL_SIMPLE_HASH(type) \
template <> \
struct Hash<type> { \
unsigned int operator() (type x) const { return x; } \
}
DECL_SIMPLE_HASH(signed char);
DECL_SIMPLE_HASH(unsigned char);
DECL_SIMPLE_HASH(signed short);
DECL_SIMPLE_HASH(unsigned short);
DECL_SIMPLE_HASH(signed int);
DECL_SIMPLE_HASH(unsigned int);
DECL_SIMPLE_HASH(signed long);
DECL_SIMPLE_HASH(unsigned long);
DECL_SIMPLE_HASH(signed long long);
DECL_SIMPLE_HASH(unsigned long long);
#undef DECL_SIMPLE_HASH
template <>
class Hash<const char*> {
static const int M = 61; // 5;
public:
unsigned int operator() (const char* s) const {
// case insensitive, so sensitivity can be turned on/off without
// effecting hash #.
unsigned h = 0;
char c;
while (c = *s++) {
if (c >= 'A' && c <= 'Z')
c = c - 'A' + 'a';
h = M*h + c;
}
return h;
}
};
template <> struct Hash<char*> : public Hash<const char*> {};
}
EDIT:: I needed to include the namespace. Working on other's code lead to foolish mistakes.
Thanks for vote down and help. :)
Any help is appreciated. Thanks.
As far as I can see:
You're not including "hash.h"
You've commented out the declaration of the Hash template, leaving only the explicit specialisations. You still need to declare the template, even if you don't define the generic version.
The Hash template is inside a namespace Hash, but you neither use that namespace nor fully qualify the template name. (By the way, it's not a very good idea to use the same name for a namespace and a class; it can lead to ambiguities).
You're trying to call a non-static operator() as if it's static; you want something more like return Hash<const char*>()(ext_str_tab_s1);.
So it's no surprise that Hash is not recognised as a template name (although it has to be said that the error message is not very helpful).
There are few possible options :
you didn't include the header where the Hash template is defined
the template Hash is in different namespace
Hash is a namespace. Namespaces can't have template parameters.
Don't give types and namespaces the same name.
I'm trying to compile code in g++ and I get the following errors:
In file included from scanner.hpp:8,
from scanner.cpp:5:
parser.hpp:14: error: ‘Scanner’ does not name a type
parser.hpp:15: error: ‘Token’ does not name a type
Here's my g++ command:
g++ parser.cpp scanner.cpp -Wall
Here's parser.hpp:
#ifndef PARSER_HPP
#define PARSER_HPP
#include <string>
#include <map>
#include "scanner.hpp"
using std::string;
class Parser
{
// Member Variables
private:
Scanner lex; // Lexical analyzer
Token look; // tracks the current lookahead token
// Member Functions
<some function declarations>
};
#endif
and here's scanner.hpp:
#ifndef SCANNER_HPP
#define SCANNER_HPP
#include <iostream>
#include <cctype>
#include <string>
#include <map>
#include "parser.hpp"
using std::string;
using std::map;
enum
{
// reserved words
BOOL, ELSE, IF, TRUE, WHILE, DO, FALSE, INT, VOID,
// punctuation and operators
LPAREN, RPAREN, LBRACK, RBRACK, LBRACE, RBRACE, SEMI, COMMA, PLUS, MINUS, TIMES,
DIV, MOD, AND, OR, NOT, IS, ADDR, EQ, NE, LT, GT, LE, GE,
// symbolic constants
NUM, ID, ENDFILE, ERROR
};
class Token
{
public:
int tag;
int value;
string lexeme;
Token() {tag = 0;}
Token(int t) {tag = t;}
};
class Num : public Token
{
public:
Num(int v) {tag = NUM; value = v;}
};
class Word : public Token
{
public:
Word() {tag = 0; lexeme = "default";}
Word(int t, string l) {tag = t; lexeme = l;}
};
class Scanner
{
private:
int line; // which line the compiler is currently on
int depth; // how deep in the parse tree the compiler is
map<string,Word> words; // list of reserved words and used identifiers
// Member Functions
public:
Scanner();
Token scan();
string printTag(int);
friend class Parser;
};
#endif
anyone see the problem? I feel like I'm missing something incredibly obvious.
parser.hpp incluser scanner.hpp and vice versa.
So one file evalated before the other.
You can use a forward declaration like
class Scanner;
or reorginaze your headers
You are including Scanner.hpp in Parser.hpp and you are also including Parser.hpp in Scanner.hpp.
If you include Scanner.hpp in your source file then the definition of the Parser class will appear before the definition of the Scanner class and you will get the error you are seeing.
Resolve the circular dependency and your problem will go away (headers should never circularly depend on each other for types).
You have circular #include reference: one header file includes another and vice versa. You need to break this loop somehow.