Segmentation fault driven of a null reference in a c++ header file - c++

Can anyone find out what is wrong with the following part of code:
private:
TUcdFileReader& operator = (const TUcdFileReader& r) { Fail; return *((TUcdFileReader *) 0); }
TUcdFileReader(const TUcdFileReader& r) { Fail; }
This belongs to a header file in a c library (SNAP) which I use in my code. When I compile my code in a linux based system, the below warning shows up:
Snap-2.1/glib-core/unicode.h(1678): warning #327: NULL reference is not allowed
TUcdFileReader& operator = (const TUcdFileReader& r) { Fail; return *((TUcdFileReader *) 0); }
Which in overall lead me to a segmentation fault as follows: (and I suspect it is because of the above warning)
WARNING: Job died due to SIGSEGV - Invalid memory reference
I dont write the whole header file since it is long and makes confusion, but it is the address of it: http://snap.stanford.edu/snap/doc/snapuser-ref/dd/d90/unicode_8h_source.html
Here I wrote the bigger part of header file that uses TUcdFileReader:
protected:
class TUcdFileReader
{
protected:
TChA buf;
public:
TChA comment; // contains '#' and everything after it
protected:
FILE *f;
int putBackCh;
int GetCh() {
if (putBackCh >= 0) { int c = putBackCh; putBackCh = EOF; return c; }
return fgetc(f); }
void PutBack(int c) { Assert(putBackCh == EOF); putBackCh = c; }
// Returns 'false' iff the EOF was encountered before anything was read.
bool ReadNextLine() {
buf.Clr(); comment.Clr();
bool inComment = false, first = true;
while (true) {
int c = GetCh();
if (c == EOF) return ! first;
else if (c == 13) {
c = GetCh(); if (c != 10) PutBack(c);
return true; }
else if (c == 10) return true;
else if (c == '#') inComment = true;
if (! inComment) buf += char(c);
else comment += char(c); }
/*first = false;*/}
private:
TUcdFileReader& operator = (const TUcdFileReader& r) { Fail; return *((TUcdFileReader *) 0); }
TUcdFileReader(const TUcdFileReader& r) { Fail; }
public:
TUcdFileReader() : f(0) { }
TUcdFileReader(const TStr& fileName) : f(0), putBackCh(EOF) { Open(fileName); }
void Open(const TStr& fileName) { Close(); f = fopen(fileName.CStr(), "rt"); IAssertR(f, fileName); putBackCh = EOF; }
void Close() { putBackCh = EOF; if (f) { fclose(f); f = 0; }}
~TUcdFileReader() { Close(); }
bool GetNextLine(TStrV& dest) {
dest.Clr();
while (true) {
if (! ReadNextLine()) return false;
TStr line = buf; line.ToTrunc();
if (line.Len() <= 0) continue;
line.SplitOnAllCh(';', dest, false);
for (int i = 0; i < dest.Len(); i++) dest[i].ToTrunc();
return true; }}
static int ParseCodePoint(const TStr& s) {
int c; bool ok = s.IsHexInt(true, 0, 0x10ffff, c); IAssertR(ok, s); return c; }
static void ParseCodePointList(const TStr& s, TIntV& dest, bool ClrDestP = true) { // space-separated list
if (ClrDestP) dest.Clr();
TStrV parts; s.SplitOnWs(parts);
for (int i = 0; i < parts.Len(); i++) {
int c; bool ok = parts[i].IsHexInt(true, 0, 0x10ffff, c); IAssertR(ok, s);
dest.Add(c); } }
static void ParseCodePointRange(const TStr& s, int& from, int &to) { // xxxx or xxxx..yyyy
int i = s.SearchStr(".."); if (i < 0) { from = ParseCodePoint(s); to = from; return; }
from = ParseCodePoint(s.GetSubStr(0, i - 1));
to = ParseCodePoint(s.GetSubStr(i + 2, s.Len() - 1)); }
};
Further, the only place that TUcdFileReader is called :
class TSubcatHelper
{
public:
bool hasCat; TUniChSubCategory subCat;
TStrH invalidCatCodes;
TUniChDb &owner;
TSubcatHelper(TUniChDb &owner_) : owner(owner_) { }
void ProcessComment(TUniChDb::TUcdFileReader &reader)
{
....

The class TUcdFileReader is specifically defined as NOT having assignment or copy constructors, i.e.
private:
TUcdFileReader& operator = (const TUcdFileReader& r)
{ Fail; return *((TUcdFileReader *) 0); }
TUcdFileReader(const TUcdFileReader& r) { Fail; }
looks like they are meant to fail.
Somewhere in the code they are being called - if you replacing those with:
private:
TUcdFileReader& operator = (const TUcdFileReader& r); //**not implemented**
TUcdFileReader(const TUcdFileReader& r); //**not implemented**
then you'd get a linker error. Best fix would be (if possible) to implement them.

Related

Repeating words in string class

So I have to write a string class, and I need help with reading from a file into a vector of string classes I've created. It somewhat works, as it reads from the file but it repeats the the word read in a few times depending on which word it's on.
// .h
/*Class description:
A string class. Various functions for the class.
String is passed into objects of the class. Reads
and writes to files.*/
#ifndef MYString12_H
#define MYString12_H
#include <fstream>
using namespace std;
class MYString12
{
public:
MYString12();
MYString12(const MYString12 & mstr);
MYString12(const char* ptr);
~MYString12();
MYString12& operator = (const MYString12& argStr);
friend MYString12 operator + (const MYString12& str1, const MYString12& str2);
char operator [] (int index);
bool operator > (const MYString12& argStr2);
bool operator < (const MYString12& argStr2);
bool operator == (const MYString12& argStr);
friend istream& operator >> (istream& istr, MYString12& argStr);
friend ostream& operator << (ostream& istr, MYString12& argStr);
int length() const;
int capacity()const;
char at(int index);
const char* c_str()const;
static int getCurrentCount();
static int getCreatedCount();
private:
char* str;
int cap = 20;
int end;
const int compareTo(const MYString12& argStr);
static int currentCount;
static int createdCount;
};
#endif
Here is class cpp file
// MYString12.cpp
#include "stdafx.h"
#include "MYString12.h"
#include <iostream>
#include <iomanip>
#include <math.h>
#include <cstdlib>
using namespace std;
int MYString12::createdCount = 0;
int MYString12::currentCount = 0;
// default constructor
MYString12::MYString12()
{
cap = 20;
end = 0;
str = new char[cap];
str[end] = '\0';
createdCount++;
currentCount++;
}
// copy constructor
MYString12::MYString12(const MYString12& mstr)
{
this->end = mstr.end;
this->cap = mstr.cap;
this->str = new char[mstr.cap];
while (end >= cap) {
cap += 20;
}
for (int i = 0; i < end; i++) {
str[i] = mstr.str[i];
}
//mstr.str[end] = '\0';
createdCount++;
currentCount++;
}
// constructor with string passed in
MYString12::MYString12(const char* ptr)
{
int i = 0;
while (ptr[i] != '\0') {
end++;
i++;
}
while (end >= cap) {
cap += 20;
}
str = new char[cap];
for (int j = 0; j < end; j++) {
str[j] = ptr[j];
}
createdCount++;
currentCount++;
}
// destructor
MYString12::~MYString12()
{
delete[] str;
currentCount--;
}
// overloaded assignment operator
GAString12& GAString12::operator = (const GAString12& mstr)
{
if (this == &mstr) {
return *this;
}
this->end = mstr.end;
this->cap = mstr.cap;
while (end >= cap) {
cap += 20;
}
for (int i = 0; i < end; i++) {
str[i] = mstr.str[i];
}
//mstr.str[end] = '\0';
return *this;
}
// overloaded concatanation operator
MYString12 operator + (const MYString12& str1, const MYString12& str2)
{
int temp = str1.end + str2.end + 1;
char tempArray[200];
int i = 0;
int j = 0;
while (i < temp)
{
if (i < str1.end)
{
tempArray[i] = str1.str[i];
i++;
} else {
tempArray[i] = str2.str[j];
i++;
j++;
}
}
tempArray[i] = '\0';
MYString12 concatenatedObj(tempArray);
return concatenatedObj;
}
// overloaded index operator
char MYString12::operator [] (int index)
{
return str[index];
}
// overloaded greater than operator
bool MYString12::operator > (const MYString12& argStr)
{
if ((*this).compareTo(argStr) > 0)
{
return true;
}
else {
return false;
}
}
// overloaded less than operator
bool MYString12::operator < (const MYString12& argStr)
{
if ((*this).compareTo(argStr) < 0)
{
return true;
}
else {
return false;
}
}
// overloaded equals equals operator
bool MYString12::operator == (const MYString12& argStr)
{
if ((*this).compareTo(argStr) == 0)
{
return true;
}
else {
return false;
}
}
// compares ascii values of objStr and argStr
const int MYString12::compareTo(const MYString12& argStr)
{
int asciiSubtraction = 0;
int limit = 0;
if (end <= argStr.end)
{
limit = end;
}
else {
limit = argStr.end;
}
int i = 0;
while (i <= limit && (str[i] == argStr.str[i])) {
i++;
}
asciiSubtraction = str[i] - argStr.str[i];
return asciiSubtraction;
}
// overloaded extraction operator
istream& operator >> (istream& istr, MYString12& argStr)
{
char temp[100];
istr >> temp;
argStr = GAString12(temp);
return istr;
}
// overloaded insertion operator
ostream& operator << (ostream& ostr, MYString12& argStr)
{
int i = 0;
while (argStr.str[i] != '\0')
{
ostr << argStr.str;
i++;
}
return ostr;
}
// returns size of passed in string
int MYString12::length() const
{
return end;
}
// returns size of memory allocated
int MYString12::capacity() const
{
return cap;
}
// returns a char of string at passed index
char MYString12::at(int index)
{
if (index < 0 || index > end) {
return '\0';
}
else {
return str[index];
}
}
// returns passed in string as c string
const char* MYString12::c_str() const
{
createdCount++;
currentCount++;
return str;
}
// returns the amount of alive instances of class
int MYString12::getCurrentCount()
{
return currentCount;
}
// returns the amount of overall created instances of class
int MYString12::getCreatedCount()
{
return createdCount;
}
And here is main
// main
int main()
{
vector<MYString12> word(100);
ifstream fin;
fin.open("infile3.txt");
if (fin.fail()) {
cout << "Error." << endl;
exit(1);
}
int wordCount = 0;
while (fin >> word[wordCount]) {
cout << word[wordCount];
system("pause");
wordCount++;
}
word.resize(wordCount);
fin.close();endl;
return 0;
}
It doesn't print out to the console any of the words. Nothing is printed. Why doesn't it print?

Error reading character of string C++

I showed my codes and i have an error reading character of string. Everything is okey in my debugger until the NULL.
*Warning C4715 `String::equas`: not all control paths return a value*
I can not use it because I am using a NULL pointer for the parameter.
How can I solve this problem?
Thanks a lot and have a nice day!
Header:
class String
{
public:
String();
bool empty();
String(char * other_str);
bool equals(const String other_str);
private:
char* m_str;
};
My Codes:
#include "String.hpp"
#include <string>
#include<iostream>
int my_len(const char* p) {
int c = 0;
while (*p != '\0')
{
c++;
*p++;
}
return c;
}
String::String()
:m_str(NULL)
{
}
String::String(char * other_str)
{
}
bool String::empty()
{
return true;
}
bool String::equals(const String other_str)
{
if (m_str == NULL && other_str.m_str == NULL) {
return true;
}
if (m_str == NULL && other_str.m_str != NULL) {
return false;
}
if (m_str != NULL && other_str.m_str == NULL) {
return false;
}
if (m_str != NULL && other_str.m_str != NULL) {
int mystrlen = my_len(m_str);
int myrhslen = my_len(other_str.m_str);
if (mystrlen != myrhslen)
{
return false;
}
else
{
for (int i = 0; i < mystrlen; i++)
{
if (m_str[i] != other_str.m_str[i])
{
return false;
}
else {
return true;
}
}
}
}
}
i will add this codes:
int mylen(const char* p) {
int c = 0;
while (*p != '\0')
{
c++;
*p++;
}
return c;
}
void my_cpy(char dest, const char* src) {
int i = 0;
while (src[i] != '\0') {
dest[i] = src[i];
i++;
}
dest[i] = '\0';
}
char mytrdup(const char *s) {
char* d = (char*)malloc((my_len(s) + 1) * sizeof(char));
if (d == NULL) {
return NULL;
}
else{
my_cpy(d, s);
}
return d;
}
String empty_string2(NULL);
This will invokde the constructor version :
String::String(char* other_str) {}
which does nothing, leaving the m_str pointer dangling/uninitialized. You should change this constructor somehow, either by copying the string and setting the m_str pointer accordingly, or by setting m_str to the same address as the parameter. Either case it depends on what you want to achieve.
Besides, many other problems exist in your code. I notice already this one in you implemented function my_len. you should change *p++ into p++. I wonder how this passed the compilation btw, since the parameter is a const char*.
Finally, the compiler's warning is correct and very clear, although it is not the source of the problem you are facing for the time being.
EDIT: to make a duplicate copy of the string, you can write you constructor like this:
String::String(const char* other_str)
{ m_str = (other_str ? strdup(other_str) : other_str); }
And besides, preferably use null_ptr instead of NULL in your code. Since C++11, this is the standard for null pointers.
I add TEST_TRUE and then that work correctly.

Creating custom std::streambuf

I am defining a custom std::streambuf class for use in file I/O. In this class, I am overloading the functions open, close, is_open, xsgetn, xsputn, overflow, underflow, and uflow. I then insert this buffer into an std::ifstream as follows (the same scenario holds for std::ofstream):
std::ifstream temp;
Filebuffer *buffer = new Filebuffer();
buffer->open(fileName.c_str(), std::ios_base::in | std::ios_base::binary);
temp.basic_ios<char>::rdbuf(buffer);
The implementation for Filebuffer (my custom class) is as follows:
std::streamsize
Filebuffer::xsputn(const char *s, std::streamsize n)
{
std::streamsize result = 0;
if(file && n)
{
for(;;)
{
size_t buffer_use = this->epptr() - this->pptr();
if(buffer_use > 0)
{
if(static_cast<int>(buffer_use) > n)
{
buffer_use = n;
}
std::char_traits<char>::copy(this->pptr(), s, buffer_use);
this->pbump(buffer_use);
result += buffer_use;
n -= buffer_use;
if(n == 0)
{
break;
}
s += buffer_use;
}
this->overflow(static_cast<int>(*s));
}
}
return result;
}
std::streamsize
Filebuffer::xsgetn(char *s, std::streamsize n)
{
std::streamsize result = 0;
if(file && n)
{
int ch; do
{
size_t buffer_use = this->egptr() - this->gptr();
if(buffer_use > 0)
{
if(static_cast<int>(buffer_use) > n)
{
buffer_use = n;
}
std::char_traits<char>::copy(s, this->gptr(), buffer_use);
this->gbump(buffer_use);
result += buffer_use;
n -= buffer_use;
if(n == 0)
{
break;
}
s += buffer_use;
}
ch = this->underflow();
} while(!(ch == std::char_traits<char>::eof()));
}
return result;
}
int
Filebuffer::underflow()
{
if(file)
{
nullify_put_area(); //clears write buffer
if(!buffer) //allocated in open()
{
int value = ungetc(fgetc(file), file);
if(value == EOF)
{
return std::char_traits<char>::eof();
}
return value;
}
char *begin = buffer;
char *end = buffer + bufferSize - 1; //bufferSize set to 4 KB
char *next = end;
if(this->gptr() < this->egptr())
{
size_t buffer_use = this->egptr() - this->gptr();
memmove(begin, next, buffer_use);
begin += buffer_use;
}
setg(begin, begin, begin);
size_t m = (bufferSize - 1 - (begin - this->eback()));
if(m > 0)
{
size_t status = fread(begin, 1, m, file);
if(status == 0)
{
return std::char_traits<char>::eof();
}
setg(this->eback(), this->gptr(), begin + status);
}
return static_cast<int>(*this->gptr());
}
return std::char_traits<char>::eof();
}
int
Filebuffer::uflow()
{
if(!file)
{
return std::char_traits<char>::eof();
}
int ch = underflow();
if(ch != std::char_traits<char>::eof())
{
if(buffer)
{
this->gbump(1);
}
else
{
fgetc(file);
}
}
return ch;
}
int
Filebuffer::overflow(int c)
{
if(!file)
{
return std::char_traits<char>::eof();
}
const char *begin = this->pbase();
char *next = this->pptr();
if(buffer)
{
setp(buffer, buffer + bufferSize - 1);
}
nullify_get_area(); //clears read buffer
char temp;
if(c == std::char_traits<char>::eof())
{
c = std::char_traits<char>::not_eof(std::char_traits<char>::eof());
}
else
{
if(!next)
{
begin = next = &temp;
}
assert(next == &temp || buffer <= next);
assert(next == &temp || next < buffer + bufferSize);
*next++ = static_cast<char>(c);
}
if(begin != next)
{
if(begin == &temp)
{
fputc(temp, file);
return c;
}
size_t n = next - begin;
size_t status = fwrite(begin, 1, n, file);
if(status != n)
{
return std::char_traits<char>::eof();
}
return c;
}
return std::char_traits<char>::eof();
}
Unfortunately, whenever I use (e.g.) temp >> readVar;, it does not use any of my overloaded functions - the call stack shows that the STL original implementations were called - and instead, simply reads in garbage. Per this question, I need to define overflow for ofstream (and presumably, underflow for ifstream), which I have done. Am I defining xsputn and xsgetn correctly? Why are my overloaded functions not being called?
It appears that trying to do this with std::ifstream will not work, and I need to change it std::istream. Once I make this change, the overloaded functions are called and everything works properly.

std::vector::resize results in a crash in a template class

Here's the code :
The place where it crashed is marked with a comment(//////crash).
I don't know what results in the problem.
After I print the size of data got from file,It shows '1' means that the array should only contains 1 element. So it seems that there's no 'bad_allocate error' ...
Could you guys help me ? I would appreciate your kindly help very much. :)
#include<stdio.h>
#include<iostream>
#include<string>
#include<map>
#include<vector>
#include<algorithm>
#include<string.h>
#include<type_traits>
using namespace std;
bool read_int(int& val,FILE*& fp)
{
if(fp == nullptr)
return false;
fread(&val,sizeof(int),1,fp);
return true;
}
bool write_int(int val,FILE*& fp)
{
if(fp == nullptr)
{
return false;
}
fwrite(&val,sizeof(int),1,fp);
return true;
}
struct SANOBJ
{
char path[128];
char nickname[40];
SANOBJ(const char* _p = nullptr,const char* _n = nullptr)
{
if(_p == nullptr || _n == nullptr)
*this = {};
int m = strlen(_p),n = strlen(_n);
if(m < 128) strcpy(path,_p);
if(n < 40) strcpy(nickname,_n);
}
~SANOBJ(){}
SANOBJ(const SANOBJ& other)
{
memcpy(path,other.path,sizeof(char) * 128);
memcpy(nickname,other.nickname,sizeof(char) * 40);
}
bool operator < (const SANOBJ& other) const
{
return string(path) < string(other.path);
}
bool operator == (const SANOBJ& other) const
{
return (strcmp(other.path,path) == 0);
}
};
template <typename source_type> //the 'source_type' type need to have the member 'int m_index'
class FrameQueue
{
public:
FrameQueue() //fill the 1st frame automatically
{
source_type new_node;
new_node.m_index = 0;
m_data.push_back(new_node);
}
FrameQueue(const FrameQueue& other)
{
m_data = other.m_data;
}
bool AddFrame(const source_type& other) // keeps an ascending order
{
int index = _binary_search(other);
if(index != -1)
{
return false;
}
m_data.insert(std::upper_bound(m_data.begin(),m_data.end(),other,
[](const source_type& a,const source_type& b)->bool const{return a.m_index < b.m_index;}
),other);
return true;
}
bool DeleteFrameByElemIndex(int elemIndex) //delete frame according to the index of frame in the queue
{
if(elemIndex < 0)
return false;
if(elemIndex >= m_data.size())
return false;
typename std::vector<source_type>::iterator it ;
it = m_data.begin() + elemIndex;
it = m_data.erase(it);
return true;
}
bool DeleteFrameByFrameIndex(int frameIndex)
{
source_type node = {};
node.m_index = frameIndex;
int index = _binary_search(node);
if(index == -1)
{
return false;
}
typename std::vector<source_type>::iterator it;
it = m_data.begin() + index;
it = m_data.erase(it);
return true;
}
bool Clear() // There would always be a single frame
{
source_type new_node = {};
new_node.m_index = 0;
m_data.clear();
m_data.push_back(new_node);
return true;
}
bool WriteFile(FILE*& fp)
{
if(fp == nullptr)
return false;
bool result = write_int(m_data.size(),fp);
if(result == false)
return false;
fwrite(&(m_data[0]),sizeof(source_type),m_data.size(),fp);
return true;
}
bool ReadFile(FILE*& fp)
{
if(fp == nullptr)
return false;
int data_size;
bool result = read_int(data_size,fp);
if(result == false)
return false;
if(data_size > 0)
{
m_data.resize(data_size);
fread(&(m_data[0]),sizeof(source_type),data_size,fp);
}
return true;
}
private:
int _binary_search(source_type target)
{
int l = 0,r = (int)m_data.size() - 1,mid;
while(l<=r)
{
mid = (l + r) / 2;
if(m_data[l].m_index == target.m_index)
{
return l;
}
if(m_data[r].m_index == target.m_index)
{
return r;
}
if(m_data[mid].m_index == target.m_index)
{
return mid;
}
if(m_data[mid].m_index > target.m_index)
{
r = mid - 1;
}
else
{
l = mid + 1;
}
}
return -1;
}
public:
vector<source_type> m_data;
};
template<typename source_type>
class UniqueSource
{
public:
UniqueSource(){}
~UniqueSource(){}
bool Add(const source_type& other)//return false when insert failed,otherwise return true
{
if(m_map_source_to_index.find(other) == m_map_source_to_index.end())
{
int map_size = m_map_source_to_index.size();
m_data.push_back(other);
m_map_source_to_index.insert(pair<source_type,int>(other,map_size));
m_result.push_back(map_size);
return true;
}
else
{
m_result.push_back(m_map_source_to_index[other]);
return true;
}
return false;
}
bool Delete(int elemIndex) // delete the elem by elem Index,If succeed ,return true,otherwise return false
{
if(elemIndex < 0)
return false;
if(elemIndex >= m_data.size())
return false;
typename std::map<source_type,int>::iterator mit;
typename std::vector<source_type>::iterator vit;
for(mit = m_map_source_to_index.begin();mit!=m_map_source_to_index.end();++mit)
{
m_map_source_to_index.erase(mit);
}
vit = m_data.begin() + elemIndex;
m_data.erase(vit);
return true;
}
bool Clear()
{
m_map_source_to_index.clear();
m_data.clear();
m_result.clear();
return true;
}
bool WriteFile(FILE*& fp)
{
if(fp == nullptr)
return false;
bool result = write_int(m_data.size(),fp);
if(result == false)
return false;
if(m_data.size() > 0)
fwrite(&(m_data[0]),sizeof(source_type),m_data.size(),fp);
result = write_int(m_result.size(),fp);
if(result == false)
return false;
if(m_result.size() > 0)
fwrite(&(m_result[0]),sizeof(int),m_result.size(),fp);
return true;
}
bool ReadFile(FILE*& fp)
{
if(fp == nullptr)
return false;
Clear();
int data_size;
read_int(data_size,fp);
if(data_size > 0)
{
printf("[%d]",data_size);
m_data.resize(data_size); /////////////////Crash!!!!!!!!!!!!
printf("Resize Ok\r\n");
fread(&(m_data[0]),sizeof(source_type),data_size,fp);
}
read_int(data_size,fp);
printf("[%d]",data_size);
if(data_size > 0)
{
m_result.resize(data_size);
fread(&(m_result[0]),sizeof(int),data_size,fp);
}
return true;
}
//private:
map<source_type,int> m_map_source_to_index;
vector<source_type> m_data;
vector<int> m_result; //the index I want
};
int main()
{
UniqueSource<SANOBJ> m;
SANOBJ t = {"123","456"};
m.Add(t);
printf("Added\r\n");
FILE* fp = nullptr;
fp = fopen("test.b","wb");
if(fp == nullptr)
{
printf("Failed...\r\n");
}
bool ret = false;
ret = m.WriteFile(fp);
if(ret)
{
printf("Writed!\r\n");
fclose(fp);
}
fp = fopen("test.b","rb");
if(fp == nullptr)
{
printf("Failed...\r\n");
}
ret = m.ReadFile(fp);
fclose(fp);
printf("Readed\r\n");
for(int i=0;i<m.m_data.size();i++)
printf("%s %s\r\n",m.m_data[i].path,m.m_data[i].nickname);
return 0;
}
*this = {} default-constructs a new SANOBJ instance and then assigns it to *this. This would normally be OK, but here you are calling it from the SANOBJ default constructor (making the logic being something like "to default-construct a SANOBJ, default-construct a SANOBJ and then assign its value to myself"), leading to infinite recursion and eventually a stack overflow.
Sidenote: The copy constructor is not needed.
Yes. The problem is is with *this = {}
If I were you, I'd rewrite SANOBJ constructor like this (this is a rough code and you may need to slightly modify it if you wish)
SANOBJ(const char* _p = nullptr,const char* _n = nullptr)
{
if (( _p != nullptr ) && ((strlen(_p) < 128)))
strcpy(path,_p);
if (( _n != nullptr ) && ((strlen(_n) < 40)))
strcpy(nickname,_n);
}
It'll resolve the problem.
Naturally, I don't play with *this (not this).
If you want to be sure that the member variables are empty (char path[128] and char nickname[40])
set at the beginning of the constructor something like:
path[0] = '\0';
nickname[0] = '\0';
Or use something like on constructor:
SANOBJ(const char* _p = nullptr,const char* _n = nullptr)
: path(), nickname()
{
}
But don't use *this= {}

"ambiguous symbol error" while building a C++/Tcl program using boost library

I have gone through the guides given out here & http://cpptcl.sourceforge.net/doc/compiling.html Hence I have pretty much done the basic stuffs.
Here's the code for Hello.cc given in the guide present in C++/Tcl:
#include "cpptcl.h"
#include <iostream>
using namespace std;
void hello()
{
cout << "Hello C++/Tcl!" << endl;
}
CPPTCL_MODULE(Mymodule, i)
{
i.def("hello", hello);
}
According to the guide, we need cpptcl.h & cpptcl.cc & few other files in details/ directory which I have included.
While building the code, it's giving me the following error:
1>Compiling...
1>cpptcl.cc
cpptcl.cc(35) : warning C4800: 'int' : forcing value to bool 'true' or 'false' (performance warning)
cpptcl.cc(325) : error C2039: 'what' : is not a member of 'boost::exception'
1> c:\program files\boost\boost_1_44_0\boost\exception\exception.hpp(194) : see declaration of 'boost::exception'
1>cpptcl.cc(366) : error C2872: 'exception' : ambiguous symbol
1> could be 'c:\program files\boost\boost_1_44_0\boost\exception\exception.hpp(194) : boost::exception'
1> or 'c:\program files\microsoft visual studio 8\vc\include\exception(88) : std::exception'
1>cpptcl.cc(368) : error C2039: 'what' : is not a member of 'boost::exception'
1>c:\program files\boost\boost_1_44_0\boost\exception\exception.hpp(194) : see declaration of 'boost::exception'
1>3 error(s), 2 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
It's not able to resolve exception symbol. I am not sure whether the exception.hpp or the std::exception.
Below is the code for cpptcl.cc
//
// Copyright (C) 2004-2005, Maciej Sobczak
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
#include "cpptcl.h"
#include
#include
#include
#include
using namespace Tcl;
using namespace Tcl::details;
using namespace std;
using namespace boost;
result::result(Tcl_Interp *interp) : interp_(interp) {}
result::operator bool() const
{
Tcl_Obj *obj = Tcl_GetObjResult(interp_);
int val, cc;
cc = Tcl_GetBooleanFromObj(interp_, obj, &val);
if (cc != TCL_OK)
{
throw tcl_error(interp_);
}
return static_cast(val);
}
result::operator double() const
{
Tcl_Obj *obj = Tcl_GetObjResult(interp_);
double val;
int cc = Tcl_GetDoubleFromObj(interp_, obj, &val);
if (cc != TCL_OK)
{
throw tcl_error(interp_);
}
return val;
}
result::operator int() const
{
Tcl_Obj *obj = Tcl_GetObjResult(interp_);
int val, cc;
cc = Tcl_GetIntFromObj(interp_, obj, &val);
if (cc != TCL_OK)
{
throw tcl_error(interp_);
}
return val;
}
result::operator long() const
{
Tcl_Obj *obj = Tcl_GetObjResult(interp_);
long val;
int cc;
cc = Tcl_GetLongFromObj(interp_, obj, &val);
if (cc != TCL_OK)
{
throw tcl_error(interp_);
}
return val;
}
result::operator string() const
{
Tcl_Obj *obj = Tcl_GetObjResult(interp_);
return Tcl_GetString(obj);
}
result::operator object() const
{
return object(Tcl_GetObjResult(interp_));
}
void details::set_result(Tcl_Interp *interp, bool b)
{
Tcl_SetObjResult(interp, Tcl_NewBooleanObj(b));
}
void details::set_result(Tcl_Interp *interp, int i)
{
Tcl_SetObjResult(interp, Tcl_NewIntObj(i));
}
void details::set_result(Tcl_Interp *interp, long i)
{
Tcl_SetObjResult(interp, Tcl_NewLongObj(i));
}
void details::set_result(Tcl_Interp *interp, double d)
{
Tcl_SetObjResult(interp, Tcl_NewDoubleObj(d));
}
void details::set_result(Tcl_Interp *interp, string const &s)
{
Tcl_SetObjResult(interp,
Tcl_NewStringObj(s.data(), static_cast(s.size())));
}
void details::set_result(Tcl_Interp *interp, void *p)
{
ostringstream ss;
ss (s.size())));
}
void details::set_result(Tcl_Interp *interp, object const &o)
{
Tcl_SetObjResult(interp, o.get_object());
}
void details::check_params_no(int objc, int required)
{
if (objc > callback_interp_map;
typedef map callback_map;
callback_map callbacks;
callback_map constructors;
// map of call policies
typedef map policies_interp_map;
typedef map policies_map;
policies_map call_policies;
// map of object handlers
typedef map > class_interp_map;
typedef map class_handlers_map;
class_handlers_map class_handlers;
// helper for finding call policies - returns true when found
bool find_policies(Tcl_Interp *interp, string const &cmdName,
policies_interp_map::iterator &piti)
{
policies_map::iterator pit = call_policies.find(interp);
if (pit == call_policies.end())
{
return false;
}
piti = pit->second.find(cmdName);
return piti != pit->second.end();
}
extern "C"
int object_handler(ClientData cd, Tcl_Interp *interp,
int objc, Tcl_Obj * CONST objv[]);
// helper function for post-processing call policies
// for both free functions (isMethod == false)
// and class methods (isMethod == true)
void post_process_policies(Tcl_Interp *interp, policies &pol,
Tcl_Obj * CONST objv[], bool isMethod)
{
// check if it is a factory
if (!pol.factory_.empty())
{
class_handlers_map::iterator it = class_handlers.find(interp);
if (it == class_handlers.end())
{
throw tcl_error(
"Factory was registered for unknown class.");
}
class_interp_map::iterator oit = it->second.find(pol.factory_);
if (oit == it->second.end())
{
throw tcl_error(
"Factory was registered for unknown class.");
}
class_handler_base *chb = oit->second.get();
// register a new command for the object returned
// by this factory function
// if everything went OK, the result is the address of the
// new object in the 'pXXX' form
// - the new command will be created with this name
Tcl_CreateObjCommand(interp,
Tcl_GetString(Tcl_GetObjResult(interp)),
object_handler, static_cast(chb), 0);
}
// process all declared sinks
// - unregister all object commands that envelopes the pointers
for (vector::iterator s = pol.sinks_.begin();
s != pol.sinks_.end(); ++s)
{
if (isMethod == false)
{
// example: if there is a declared sink at parameter 3,
// and the Tcl command was:
// % fun par1 par2 PAR3 par4
// then the index 3 correctly points into the objv array
int index = *s;
Tcl_DeleteCommand(interp, Tcl_GetString(objv[index]));
}
else
{
// example: if there is a declared sink at parameter 3,
// and the Tcl command was:
// % $p method par1 par2 PAR3 par4
// then the index 3 needs to be incremented
// in order correctly point into the 4th index of objv array
int index = *s + 1;
Tcl_DeleteCommand(interp, Tcl_GetString(objv[index]));
}
}
}
// actual functions handling various callbacks
// generic callback handler
extern "C"
int callback_handler(ClientData cd, Tcl_Interp *interp,
int objc, Tcl_Obj * CONST objv[])
{
callback_map::iterator it = callbacks.find(interp);
if (it == callbacks.end())
{
Tcl_SetResult(interp,
"Trying to invoke non-existent callback (wrong interpreter?)",
TCL_STATIC);
return TCL_ERROR;
}
string cmdName(Tcl_GetString(objv[0]));
callback_interp_map::iterator iti = it->second.find(cmdName);
if (iti == it->second.end())
{
Tcl_SetResult(interp,
"Trying to invoke non-existent callback (wrong cmd name?)",
TCL_STATIC);
return TCL_ERROR;
}
policies_map::iterator pit = call_policies.find(interp);
if (pit == call_policies.end())
{
Tcl_SetResult(interp,
"Trying to invoke callback with no known policies",
TCL_STATIC);
return TCL_ERROR;
}
policies_interp_map::iterator piti;
if (find_policies(interp, cmdName, piti) == false)
{
Tcl_SetResult(interp,
"Trying to invoke callback with no known policies",
TCL_STATIC);
return TCL_ERROR;
}
policies &pol = piti->second;
try
{
iti->second->invoke(interp, objc, objv, pol);
post_process_policies(interp, pol, objv, false);
}
catch (boost::exception const &e)
{
Tcl_SetResult(interp, const_cast(e.what()), TCL_VOLATILE);
return TCL_ERROR;
}
catch (...)
{
Tcl_SetResult(interp, "Unknown error.", TCL_STATIC);
return TCL_ERROR;
}
return TCL_OK;
}
// generic "object" command handler
extern "C"
int object_handler(ClientData cd, Tcl_Interp *interp,
int objc, Tcl_Obj * CONST objv[])
{
// here, client data points to the singleton object
// which is responsible for managing commands for
// objects of a given type
class_handler_base *chb = reinterpret_cast(cd);
// the command name has the form 'pXXX' where XXX is the address
// of the "this" object
string const str(Tcl_GetString(objv[0]));
istringstream ss(str);
char dummy;
void *p;
ss >> dummy >> p;
try
{
string methodName(Tcl_GetString(objv[1]));
policies &pol = chb->get_policies(methodName);
chb->invoke(p, interp, objc, objv, pol);
post_process_policies(interp, pol, objv, true);
}
catch (exception const &e)
{
Tcl_SetResult(interp, const_cast(e.what()), TCL_VOLATILE);
return TCL_ERROR;
}
catch (...)
{
Tcl_SetResult(interp, "Unknown error.", TCL_STATIC);
return TCL_ERROR;
}
return TCL_OK;
}
// generic "constructor" command
extern "C"
int constructor_handler(ClientData cd, Tcl_Interp *interp,
int objc, Tcl_Obj * CONST objv[])
{
// here, client data points to the singleton object
// which is responsible for managing commands for
// objects of a given type
class_handler_base *chb = reinterpret_cast(cd);
callback_map::iterator it = constructors.find(interp);
if (it == constructors.end())
{
Tcl_SetResult(interp,
"Trying to invoke non-existent callback (wrong interpreter?)",
TCL_STATIC);
return TCL_ERROR;
}
string className(Tcl_GetString(objv[0]));
callback_interp_map::iterator iti = it->second.find(className);
if (iti == it->second.end())
{
Tcl_SetResult(interp,
"Trying to invoke non-existent callback (wrong class name?)",
TCL_STATIC);
return TCL_ERROR;
}
policies_interp_map::iterator piti;
if (find_policies(interp, className, piti) == false)
{
Tcl_SetResult(interp,
"Trying to invoke callback with no known policies",
TCL_STATIC);
return TCL_ERROR;
}
policies &pol = piti->second;
try
{
iti->second->invoke(interp, objc, objv, pol);
// if everything went OK, the result is the address of the
// new object in the 'pXXX' form
// - we can create a new command with this name
Tcl_CreateObjCommand(interp,
Tcl_GetString(Tcl_GetObjResult(interp)),
object_handler, static_cast(chb), 0);
}
catch (std::exception const &e)
{
Tcl_SetResult(interp, const_cast(e.what()), TCL_VOLATILE);
return TCL_ERROR;
}
catch (...)
{
Tcl_SetResult(interp, "Unknown error.", TCL_STATIC);
return TCL_ERROR;
}
return TCL_OK;
}
} // namespace anonymous
Tcl::details::no_init_type Tcl::no_init;
policies & policies::factory(string const &name)
{
factory_ = name;
return *this;
}
policies & policies::sink(int index)
{
sinks_.push_back(index);
return *this;
}
policies & policies::variadic()
{
variadic_ = true;
return *this;
}
policies Tcl::factory(string const &name)
{
return policies().factory(name);
}
policies Tcl::sink(int index)
{
return policies().sink(index);
}
policies Tcl::variadic()
{
return policies().variadic();
}
class_handler_base::class_handler_base()
{
// default policies for the -delete command
policies_["-delete"] = policies();
}
void class_handler_base::register_method(string const &name,
shared_ptr ocb, policies const &p)
{
methods_[name] = ocb;
policies_[name] = p;
}
policies & class_handler_base::get_policies(string const &name)
{
policies_map_type::iterator it = policies_.find(name);
if (it == policies_.end())
{
throw tcl_error("Trying to use non-existent policy: " + name);
}
return it->second;
}
object::object()
: interp_(0)
{
obj_ = Tcl_NewObj();
Tcl_IncrRefCount(obj_);
}
object::object(bool b)
: interp_(0)
{
obj_ = Tcl_NewBooleanObj(b);
Tcl_IncrRefCount(obj_);
}
object::object(char const *buf, size_t size)
: interp_(0)
{
obj_ = Tcl_NewByteArrayObj(
reinterpret_cast(buf),
static_cast(size));
Tcl_IncrRefCount(obj_);
}
object::object(double d)
: interp_(0)
{
obj_ = Tcl_NewDoubleObj(d);
Tcl_IncrRefCount(obj_);
}
object::object(int i)
: interp_(0)
{
obj_ = Tcl_NewIntObj(i);
Tcl_IncrRefCount(obj_);
}
object::object(long l)
: interp_(0)
{
obj_ = Tcl_NewLongObj(l);
Tcl_IncrRefCount(obj_);
}
object::object(char const *s)
: interp_(0)
{
obj_ = Tcl_NewStringObj(s, -1);
Tcl_IncrRefCount(obj_);
}
object::object(string const &s)
: interp_(0)
{
obj_ = Tcl_NewStringObj(s.data(), static_cast(s.size()));
Tcl_IncrRefCount(obj_);
}
object::object(Tcl_Obj *o, bool shared)
: interp_(0)
{
init(o, shared);
}
object::object(object const &other, bool shared)
: interp_(other.get_interp())
{
init(other.obj_, shared);
}
void object::init(Tcl_Obj *o, bool shared)
{
if (shared)
{
obj_ = o;
}
else
{
obj_ = Tcl_DuplicateObj(o);
}
Tcl_IncrRefCount(obj_);
}
object::~object()
{
Tcl_DecrRefCount(obj_);
}
object & object::assign(bool b)
{
Tcl_SetBooleanObj(obj_, b);
return *this;
}
object & object::resize(size_t size)
{
Tcl_SetByteArrayLength(obj_, static_cast(size));
return *this;
}
object & object::assign(char const *buf, size_t size)
{
Tcl_SetByteArrayObj(obj_,
reinterpret_cast(buf),
static_cast(size));
return *this;
}
object & object::assign(double d)
{
Tcl_SetDoubleObj(obj_, d);
return *this;
}
object & object::assign(int i)
{
Tcl_SetIntObj(obj_, i);
return *this;
}
object & object::assign(long l)
{
Tcl_SetLongObj(obj_, l);
return *this;
}
object & object::assign(char const *s)
{
Tcl_SetStringObj(obj_, s, -1);
return *this;
}
object & object::assign(string const &s)
{
Tcl_SetStringObj(obj_, s.data(), static_cast(s.size()));
return *this;
}
object & object::assign(object const &other)
{
object(other).swap(*this);
return *this;
}
object & object::assign(Tcl_Obj *o)
{
object(o).swap(*this);
return *this;
}
object & object::swap(object &other)
{
std::swap(obj_, other.obj_);
std::swap(interp_, other.interp_);
return *this;
}
template
bool object::get(interpreter &i) const
{
int retVal;
int res = Tcl_GetBooleanFromObj(i.get(), obj_, &retVal);
if (res != TCL_OK)
{
throw tcl_error(i.get());
}
return static_cast(retVal);
}
template
vector object::get >(interpreter &) const
{
size_t size;
char const *buf = get(size);
return vector(buf, buf + size);
}
template
double object::get(interpreter &i) const
{
double retVal;
int res = Tcl_GetDoubleFromObj(i.get(), obj_, &retVal);
if (res != TCL_OK)
{
throw tcl_error(i.get());
}
return retVal;
}
template
int object::get(interpreter &i) const
{
int retVal;
int res = Tcl_GetIntFromObj(i.get(), obj_, &retVal);
if (res != TCL_OK)
{
throw tcl_error(i.get());
}
return retVal;
}
template
long object::get(interpreter &i) const
{
long retVal;
int res = Tcl_GetLongFromObj(i.get(), obj_, &retVal);
if (res != TCL_OK)
{
throw tcl_error(i.get());
}
return retVal;
}
template
char const * object::get(interpreter &) const
{
return get();
}
template
string object::get(interpreter &) const
{
int len;
char const *buf = Tcl_GetStringFromObj(obj_, &len);
return string(buf, buf + len);
}
char const * object::get() const
{
return Tcl_GetString(obj_);
}
char const * object::get(size_t &size) const
{
int len;
unsigned char *buf = Tcl_GetByteArrayFromObj(obj_, &len);
size = len;
return const_cast(reinterpret_cast(buf));
}
size_t object::length(interpreter &i) const
{
int len;
int res = Tcl_ListObjLength(i.get(), obj_, &len);
if (res != TCL_OK)
{
throw tcl_error(i.get());
}
return static_cast(len);
}
object object::at(interpreter &i, size_t index) const
{
Tcl_Obj *o;
int res = Tcl_ListObjIndex(i.get(), obj_, static_cast(index), &o);
if (res != TCL_OK)
{
throw tcl_error(i.get());
}
if (o == NULL)
{
throw tcl_error("Index out of range.");
}
return object(o);
}
object & object::append(interpreter &i, object const &o)
{
int res = Tcl_ListObjAppendElement(i.get(), obj_, o.obj_);
if (res != TCL_OK)
{
throw tcl_error(i.get());
}
return *this;
}
object & object::append_list(interpreter &i, object const &o)
{
int res = Tcl_ListObjAppendList(i.get(), obj_, o.obj_);
if (res != TCL_OK)
{
throw tcl_error(i.get());
}
return *this;
}
object & object::replace(interpreter &i, size_t index, size_t count,
object const &o)
{
int res = Tcl_ListObjReplace(i.get(), obj_,
static_cast(index), static_cast(count),
1, &(o.obj_));
if (res != TCL_OK)
{
throw tcl_error(i.get());
}
return *this;
}
object & object::replace_list(interpreter &i, size_t index, size_t count,
object const &o)
{
int objc;
Tcl_Obj **objv;
int res = Tcl_ListObjGetElements(i.get(), obj_, &objc, &objv);
if (res != TCL_OK)
{
throw tcl_error(i.get());
}
res = Tcl_ListObjReplace(i.get(), obj_,
static_cast(index), static_cast(count),
objc, objv);
if (res != TCL_OK)
{
throw tcl_error(i.get());
}
return *this;
}
void object::set_interp(Tcl_Interp *interp)
{
interp_ = interp;
}
Tcl_Interp * object::get_interp() const
{
return interp_;
}
interpreter::interpreter()
{
interp_ = Tcl_CreateInterp();
}
interpreter::interpreter(Tcl_Interp *interp, bool owner)
{
interp_ = interp;
owner_ = owner;
}
interpreter::~interpreter()
{
if (owner_)
{
// clear all callback info belonging to this interpreter
clear_definitions(interp_);
Tcl_DeleteInterp(interp_);
}
}
void interpreter::make_safe()
{
int cc = Tcl_MakeSafe(interp_);
if (cc != TCL_OK)
{
throw tcl_error(interp_);
}
}
result interpreter::eval(string const &script)
{
int cc = Tcl_Eval(interp_, script.c_str());
if (cc != TCL_OK)
{
throw tcl_error(interp_);
}
return result(interp_);
}
result interpreter::eval(istream &s)
{
string str(
istreambuf_iterator(s.rdbuf()),
istreambuf_iterator()
);
return eval(str);
}
result interpreter::eval(object const &o)
{
int cc = Tcl_EvalObjEx(interp_, o.get_object(), 0);
if (cc != TCL_OK)
{
throw tcl_error(interp_);
}
return result(interp_);
}
void interpreter::pkg_provide(string const &name, string const &version)
{
int cc = Tcl_PkgProvide(interp_, name.c_str(), version.c_str());
if (cc != TCL_OK)
{
throw tcl_error(interp_);
}
}
void interpreter::create_alias(string const &cmd,
interpreter &targetInterp, string const &targetCmd)
{
int cc = Tcl_CreateAlias(interp_, cmd.c_str(),
targetInterp.interp_, targetCmd.c_str(), 0, 0);
if (cc != TCL_OK)
{
throw tcl_error(interp_);
}
}
void interpreter::clear_definitions(Tcl_Interp *interp)
{
// delete all callbacks that were registered for given interpreter
{
callback_map::iterator it = callbacks.find(interp);
if (it == callbacks.end())
{
// no callbacks defined for this interpreter
return;
}
callback_interp_map &imap = it->second;
for (callback_interp_map::iterator it2 = imap.begin();
it2 != imap.end(); ++it2)
{
Tcl_DeleteCommand(interp, it2->first.c_str());
}
callbacks.erase(interp);
}
// delete all constructors
{
callback_map::iterator it = constructors.find(interp);
if (it == constructors.end())
{
// no callbacks defined for this interpreter
return;
}
callback_interp_map &imap = it->second;
for (callback_interp_map::iterator it2 = imap.begin();
it2 != imap.end(); ++it2)
{
Tcl_DeleteCommand(interp, it2->first.c_str());
}
callbacks.erase(interp);
}
// delete all call policies
call_policies.erase(interp);
// delete all object handlers
// (we have to assume that all living objects were destroyed,
// otherwise Bad Things will happen)
class_handlers.erase(interp);
}
void interpreter::add_function(string const &name,
shared_ptr cb, policies const &p)
{
Tcl_CreateObjCommand(interp_, name.c_str(),
callback_handler, 0, 0);
callbacks[interp_][name] = cb;
call_policies[interp_][name] = p;
}
void interpreter::add_class(string const &name,
shared_ptr chb)
{
class_handlers[interp_][name] = chb;
}
void interpreter::add_constructor(string const &name,
shared_ptr chb, shared_ptr cb,
policies const &p)
{
Tcl_CreateObjCommand(interp_, name.c_str(),
constructor_handler, static_cast(chb.get()), 0);
constructors[interp_][name] = cb;
call_policies[interp_][name] = p;
}
int tcl_cast::from(Tcl_Interp *interp, Tcl_Obj *obj)
{
int res;
int cc = Tcl_GetIntFromObj(interp, obj, &res);
if (cc != TCL_OK)
{
throw tcl_error(interp);
}
return res;
}
long tcl_cast::from(Tcl_Interp *interp, Tcl_Obj *obj)
{
long res;
int cc = Tcl_GetLongFromObj(interp, obj, &res);
if (cc != TCL_OK)
{
throw tcl_error(interp);
}
return res;
}
bool tcl_cast::from(Tcl_Interp *interp, Tcl_Obj *obj)
{
int res;
int cc = Tcl_GetBooleanFromObj(interp, obj, &res);
if (cc != TCL_OK)
{
throw tcl_error(interp);
}
return res != 0;
}
double tcl_cast::from(Tcl_Interp *interp, Tcl_Obj *obj)
{
double res;
int cc = Tcl_GetDoubleFromObj(interp, obj, &res);
if (cc != TCL_OK)
{
throw tcl_error(interp);
}
return res;
}
string tcl_cast::from(Tcl_Interp *interp, Tcl_Obj *obj)
{
return Tcl_GetString(obj);
}
char const * tcl_cast::from(Tcl_Interp *interp, Tcl_Obj *obj)
{
return Tcl_GetString(obj);
}
object tcl_cast::from(Tcl_Interp *interp, Tcl_Obj *obj)
{
object o(obj);
o.set_interp(interp);
return o;
}
How do I resolve this?
Thanks
The code seems to refer to the regular std::exception, but the symbol gets mixed because of using both the boost and std namespaces. Maybe it's some difference between VC and gcc headers.
In any case, adding the following lines to the file solves this compiler error and another similar conflict with shared_ptr in VC2010 (at least for me):
#define shared_ptr boost::shared_ptr
#define exception std::exception
Regards,
Miguel
A project has been started to fix the problems in this library here: https://github.com/wsong83/cpptcl
I notice cpptcl.cc has the following:
try
{
iti->second->invoke(interp, objc, objv, pol);
post_process_policies(interp, pol, objv, false);
}
catch (boost::exception const &e)
{
Tcl_SetResult(interp, const_cast(e.what()), TCL_VOLATILE);
return TCL_ERROR;
}
The compiler complains that boost::exceptiondoesn't have what() (which indeed it doesn't since that's in std::exception). So you have to change this to use get_error_info().
Also, I notice that the const_cast isn't taking a template argument. This is going to be problematic.