I have read many questions like this and I am not 100% sure if mine's any different. I have searched quite a lot for the right answer but most of the answers were around macro gaurds. I had a custom string class that I derived from std::string, and later on since I was using that project in real world so I did not want to derive std::string just for the sake of extending functionality. So I moved the functions from customString.h into utils_string.h. Here is the definition:
#ifndef OPS_TOOLKIT_UTILS_STRING_H
#define OPS_TOOLKIT_UTILS_STRING_H
#include <string>
#include <algorithm>
#include <vector>
namespace utils{
namespace string{
const std::string kilikeDelimiter = "%";
void tolower(std::string& str){
//CODE
}
bool iequals(const std::string& str1,const std::string& str2){
//CODE
}
bool ilike(const std::string& str,const std::string& pattern){
//CODE
}
std::string prependAndAppendILikeDelimiter(const std::string& str) {
//CODE
}
} //namespace string
} //namespace utils
#endif
and I get complains about ...first defined here and here is exact output from compiler. Note: no class here
/tmp/ccCFVTXP.o: In function utils::string::tolower(std::basic_string<char, std::char_traits<char>, std::allocator<char> >&)':
listings.cpp:(.text+0x0): multiple definition ofutils::string::tolower(std::basic_string, std::allocator >&)'
/tmp/cczDtRdT.o:listing.cpp:(.text+0x0): first defined here
/tmp/ccCFVTXP.o: In function utils::string::iequals(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)':
listings.cpp:(.text+0x55): multiple definition ofutils::string::iequals(std::basic_string, std::allocator > const&, std::basic_string, std::allocator > const&)'
/tmp/cczDtRdT.o:listing.cpp:(.text+0x55): first defined here
/tmp/ccCFVTXP.o: In function utils::string::ilike(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)':
listings.cpp:(.text+0x118): multiple definition ofutils::string::ilike(std::basic_string, std::allocator > const&, std::basic_string, std::allocator > const&)'
/tmp/cczDtRdT.o:listing.cpp:(.text+0x118): first defined here
/tmp/ccCFVTXP.o: In function utils::string::prependAndAppendILikeDelimiter(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)':
listings.cpp:(.text+0x484): multiple definition ofutils::string::prependAndAppendILikeDelimiter(std::basic_string, std::allocator > const&)'
/tmp/cczDtRdT.o:listing.cpp:(.text+0x484): first defined here
/tmp/ccifZISK.o: In function utils::string::tolower(std::basic_string<char, std::char_traits<char>, std::allocator<char> >&)':
match_count.cpp:(.text+0x0): multiple definition ofutils::string::tolower(std::basic_string, std::allocator >&)'
/tmp/cczDtRdT.o:listing.cpp:(.text+0x0): first defined here
/tmp/ccifZISK.o: In function utils::string::iequals(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)':
match_count.cpp:(.text+0x55): multiple definition ofutils::string::iequals(std::basic_string, std::allocator > const&, std::basic_string, std::allocator > const&)'
/tmp/cczDtRdT.o:listing.cpp:(.text+0x55): first defined here
/tmp/ccifZISK.o: In function utils::string::ilike(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)':
match_count.cpp:(.text+0x118): multiple definition ofutils::string::ilike(std::basic_string, std::allocator > const&, std::basic_string, std::allocator > const&)'
/tmp/cczDtRdT.o:listing.cpp:(.text+0x118): first defined here
/tmp/ccifZISK.o: In function utils::string::prependAndAppendILikeDelimiter(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)':
match_count.cpp:(.text+0x484): multiple definition ofutils::string::prependAndAppendILikeDelimiter(std::basic_string, std::allocator > const&)'
/tmp/cczDtRdT.o:listing.cpp:(.text+0x484): first defined here
collect2: ld returned 1 exit status
I am sorry for whole mess but I didn't want to miss anything for anyone who has come across similar problem.
One more thing; where it says match_count.cpp *listing.cpp* and listings.cpp it's just using the functions defined in ::utils::string::function()
A header file cannot define code unless it is explicitly inline. Otherwise (because the preprocessor works like a giant copy/paste machine) it is as if the functions are defined once for every file that does a #include.
So add inline to each of those, or put them in a single .cpp, but not in a header.
It may be better to put your functions into a class like this (the following goes to a .h file). It's probably more common that using nested namespace.
#pragma once
#include <string>
namespace utils
{
class StringUtil
{
public:
static void tolower(std::string& str)
{
// code
}
};
}
Related
I have successfully installed the OpenABE Library - https://github.com/zeutro/openabe
But when I try to compile my own program or run the example - https://github.com/zeutro/openabe/blob/master/examples/test_cp.cpp
g++ test.cpp
I get the Error:
/tmp/ccAcWSoq.o: In function main':
test.cpp:(.text+0x29): undefined reference tooabe::InitializeOpenABE()'
test.cpp:(.text+0x6a): undefined reference to oabe::OpenABECryptoContext::OpenABECryptoContext(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool)'
test.cpp:(.text+0xea): undefined reference tooabe::OpenABECryptoContext::generateParams()'
test.cpp:(.text+0x1bf): undefined reference to oabe::OpenABECryptoContext::keygen(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
test.cpp:(.text+0x27b): undefined reference tooabe::OpenABECryptoContext::encrypt(std::__cxx11::basic_string, std::allocator >, std::__cxx11::basic_string, std::allocator > const&, std::__cxx11::basic_string, std::allocator >&)'
test.cpp:(.text+0x2dd): undefined reference to oabe::OpenABECryptoContext::decrypt(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&)'
test.cpp:(.text+0x385): undefined reference tooabe::ShutdownOpenABE()'
/tmp/ccAcWSoq.o: In function oabe::OpenABECryptoContext::~OpenABECryptoContext()':
test.cpp:(.text._ZN4oabe20OpenABECryptoContextD2Ev[_ZN4oabe20OpenABECryptoContextD5Ev]+0xf): undefined reference tovtable for oabe::OpenABECryptoContext'
collect2: error: ld returned 1 exit status
Here is the code - test.cpp
#include <iostream>
#include <string>
#include <cassert>
#include <openabe/openabe.h>
#include <openabe/zsymcrypto.h>
using namespace std;
using namespace oabe;
using namespace oabe::crypto;
int main(int argc, char **argv){
InitializeOpenABE();
OpenABECryptoContext cpabe("CP-ABE");
string ct, pt1 = "plaintext", pt2;
cpabe.generateParams();
cpabe.keygen("|attr1|attr2","key0");
cpabe.encrypt("attr1 and attr2",pt1,ct);
bool result = cpabe.decrypt("key0",ct,pt2);
assert(result && pt1 == pt2);
cout << "Message: " << pt2 << endl;
ShutdownOpenABE();
return 0;
}
Am I even compiling the file correctly?
Or is there any other issue that I cannot seem to identify?
I have the following class:
class Foo
{
public:
explicit Foo(std::vector<std::string>& functionCalls)
{
}
};
typedef boost::shared_ptr<Foo> FooPtr;
Which I try to use like this:
std::vector<std::string> functionCalls;
FooPtr foo = boost::make_shared<Foo>(functionCalls);
I compiles fine in VS20012 but it wont compile in gcc 4.3.4.
Here's the compiler error:
boost/boost_1_54_0/boost/smart_ptr/make_shared_object.hpp: In function 'typename boost::detail::sp_if_not_array<T>::type boost::make_shared(const A1&) [with T = Foo, A1 = std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >]':
main.cc:39: instantiated from here
boost/boost_1_54_0/boost/smart_ptr/make_shared_object.hpp:711: error: no matching function for call to 'Foo::Foo(const std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >&)'
Foo.h:23: note: candidates are: Foo::Foo(std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >&)
Foo.h:21: note: Foo::Foo(const Foo&)
If I change the construct of Foo to take a const then it compiles fine. However, I need to pass by reference. What do you think this issue is?
As documented here, without C++11 support make_shared can only take its arguments by const reference.
With C++11 support, it can take any reference types, and forward them to the constructor. Presumably that's what VS is doing.
As mentioned in the documentation, you can pass a non-const reference by wrapping it in boost::ref:
FooPtr foo = boost::make_shared<Foo>(boost::ref(functionCalls));
I wrote some code in source file sql_parse.cc of MySql 5.5.7rc. There I have used vector, allocator, etc but the compiler is not being linked with Standard Template Library(STL). Can anybody suggest me what should I do?
Here is the error msg :
libsql.a(sql_parse.cc.o): In function `std::vector<std::basic_string<char,
std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char,
std::char_traits<char>, std::allocator<char> > > >::push_back(std::basic_string<char,
std::char_traits<char>, std::allocator<char> > const&)':
sql_parse.cc:(.text._ZNSt6vectorISsSaISsEE9push_backERKSs[std::vector<std::basic_string<char,
std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char,
std::char_traits<char>, std::allocator<char> > > >::push_back(std::basic_string<char,
std::char_traits<char>, std::allocator<char> > const&)]+0x74): undefined reference to
`std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >,
std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >
>::_M_insert_aux(__gnu_cxx::__normal_iterator<std::basic_string<char,
std::char_traits<char>, std::allocator<char> >*, std::vector<std::basic_string<char,
std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char,
std::char_traits<char>, std::allocator<char> > > > >, std::basic_string<char,
std::char_traits<char>, std::allocator<char> > const&)'
collect2: ld returned 1 exit status
You should've given the command line. I suspect that you use gcc for linking in which case you should either use g++ or add -lstdc++ option.
I got my stl code to compile with the following
g++ -std=c++11 file.cpp -o prog
undefined reference to
std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >,
std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >
::_M_insert_aux(__gnu_cxx::__normal_iterator<std::basic_string<char,
std::char_traits<char>, std::allocator<char> >*, std::vector<std::basic_string<char,
std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char,
std::char_traits<char>, std::allocator<char> > > > >, std::basic_string<char,
std::char_traits<char>, std::allocator<char> > const&)'
That symbol is a member function of std::vector<std::string> and is a function template, so should be instantiated in your program, not in the C++ standard library.
Are you compiling with the -fno-implicit-templates option? Or using an explicit instantiation declaration (i.e. extern template) in your code and not providing the definition? Those would prevent the compiler from instantiation the template.
If you're telling the compiler not to provide implicit instantiations then you will need to add an explicit instantiation for each undefined reference:
template void std::vector<std::string>::_M_insert_aux(std::vector<std::string>::iterator, std::string const&);
#ifndef GLOBAL_H
#define GLOBAL_H
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<cmath>
using namespace std;
#endif //GLOBAL_H
Is a good start
I've got a program that uses tr1::regex, and while it compiles, it gives me very verbose linker errors.
Here's my header file MapObject.hpp:
#include <iostream>
#include <string>
#include <tr1/regex>
#include "phBaseObject.hpp"
using std::string;
namespace phObject
{
class MapObject: public phBaseObject
{
private:
string color; // must be a hex string represented as "#XXXXXX"
static const std::tr1::regex colorRX; // enforces the rule above
public:
void setColor(const string&);
(...)
};
}
Here's my implementation:
#include <iostream>
#include <string>
#include <tr1/regex>
#include "MapObject.hpp"
using namespace std;
namespace phObject
{
const tr1::regex MapObject::colorRX("#[a-fA-F0-9]{6}");
void MapObject::setColor(const string& c)
{
if(tr1::regex_match(c.begin(), c.end(), colorRX))
{
color = c;
}
else cerr << "Invalid color assignment (" << c << ")" << endl;
}
(...)
}
and now for the errors:
max#max-desktop:~/Desktop/Development/CppPartyHack/PartyHack/lib$ g++ -Wall -std=c++0x MapObject.cpp
/tmp/cce5gojG.o: In function std::tr1::basic_regex<char, std::tr1::regex_traits<char> >::basic_regex(char const*, unsigned int)':
MapObject.cpp:(.text._ZNSt3tr111basic_regexIcNS_12regex_traitsIcEEEC1EPKcj[std::tr1::basic_regex<char, std::tr1::regex_traits<char> >::basic_regex(char const*, unsigned int)]+0x61): undefined reference tostd::tr1::basic_regex >::_M_compile()'
/tmp/cce5gojG.o: In function bool std::tr1::regex_match<__gnu_cxx::__normal_iterator<char const*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, char, std::tr1::regex_traits<char> >(__gnu_cxx::__normal_iterator<char const*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, __gnu_cxx::__normal_iterator<char const*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::tr1::basic_regex<char, std::tr1::regex_traits<char> > const&, std::bitset<11u>)':
MapObject.cpp:(.text._ZNSt3tr111regex_matchIN9__gnu_cxx17__normal_iteratorIPKcSsEEcNS_12regex_traitsIcEEEEbT_S8_RKNS_11basic_regexIT0_T1_EESt6bitsetILj11EE[bool std::tr1::regex_match<__gnu_cxx::__normal_iterator<char const*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, char, std::tr1::regex_traits<char> >(__gnu_cxx::__normal_iterator<char const*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, __gnu_cxx::__normal_iterator<char const*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::tr1::basic_regex<char, std::tr1::regex_traits<char> > const&, std::bitset<11u>)]+0x53): undefined reference tobool std::tr1::regex_match<__gnu_cxx::__normal_iterator, std::allocator > >, std::allocator, std::allocator > > > >, char, std::tr1::regex_traits >(__gnu_cxx::__normal_iterator, std::allocator > >, __gnu_cxx::__normal_iterator, std::allocator > >, std::tr1::match_results<__gnu_cxx::__normal_iterator, std::allocator > >, std::allocator, std::allocator > > > > >&, std::tr1::basic_regex > const&, std::bitset<11u>)'
collect2: ld returned 1 exit status
I can't really make heads or tails of this, except for the undefined reference to std::tr1::basic_regex near the beginning. Anyone know what's going on?
Regex support for C++0x is incomplete and wasn't there for TR1, see the implementation status page for C++0x/TR1.
Boost offers an alternative TR1 implementation as well as the original library it is based on.
The answer is, even though the header is supplied, some of the methods are not supplied.
One could deduce this from Georg's answer, but after thinking up and coding a hundred lines or so based on the assumption that the nifty library was actually provided, one might be too tired for any further deductions.
I have written a class using std::tr1::regex, and I don't know how to link it. I get (sorry for the large dump...) :
$ g++ DictReader.cpp -std=c++0x
/usr/include/c++/4.4/tr1_impl/regex:2255: warning: inline function ‘bool std::tr1::regex_search(_Bi_iter, _Bi_iter, std::tr1::match_results<_Bi_iter, _Allocator>&, const std::tr1::basic_regex<_Ch_type, _Rx_traits>&, std::tr1::regex_constants::match_flag_type) [with _Bi_iter = __gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, _Allocator = std::allocator<std::tr1::sub_match<__gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >, _Ch_type = char, _Rx_traits = std::tr1::regex_traits<char>]’ used but never defined
/usr/lib/gcc/x86_64-linux-gnu/4.4.1/../../../../lib/crt1.o: In function `_start':
/build/buildd/eglibc-2.10.1/csu/../sysdeps/x86_64/elf/start.S:109: undefined reference to `main'
/tmp/ccgBkWlK.o: In function `DictReader::operator++(int)':
DictReader.cpp:(.text+0xb2a): undefined reference to `bool std::tr1::regex_search<__gnu_cxx::__normal_iterator<char const*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::tr1::sub_match<__gnu_cxx::__normal_iterator<char const*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >, char, std::tr1::regex_traits<char> >(__gnu_cxx::__normal_iterator<char const*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, __gnu_cxx::__normal_iterator<char const*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::tr1::match_results<__gnu_cxx::__normal_iterator<char const*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::tr1::sub_match<__gnu_cxx::__normal_iterator<char const*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > >&, std::tr1::basic_regex<char, std::tr1::regex_traits<char> > const&, std::bitset<11ul>)'
/tmp/ccgBkWlK.o: In function `std::tr1::basic_regex<char, std::tr1::regex_traits<char> >::basic_regex(char const*, unsigned int)':
DictReader.cpp:(.text._ZNSt3tr111basic_regexIcNS_12regex_traitsIcEEEC1EPKcj[std::tr1::basic_regex<char, std::tr1::regex_traits<char> >::basic_regex(char const*, unsigned int)]+0x75): undefined reference to `std::tr1::basic_regex<char, std::tr1::regex_traits<char> >::_M_compile()'
/tmp/ccgBkWlK.o: In function `std::tr1::basic_regex<char, std::tr1::regex_traits<char> >::basic_regex(std::tr1::basic_regex<char, std::tr1::regex_traits<char> > const&)':
DictReader.cpp:(.text._ZNSt3tr111basic_regexIcNS_12regex_traitsIcEEEC1ERKS3_[std::tr1::basic_regex<char, std::tr1::regex_traits<char> >::basic_regex(std::tr1::basic_regex<char, std::tr1::regex_traits<char> > const&)]+0x60): undefined reference to `std::tr1::basic_regex<char, std::tr1::regex_traits<char> >::_M_compile()'
collect2: ld returned 1 exit status.
What should I link against?
This is a linker error, it does not found the function you are using. TR1 is still new so it may not be implemented everywhere. I recommend you to use the boost regex library instead.