I have truncated this post. The initial post is gone in order to facilitate reading. The relevant parts and problems are still there.
UPDATE
The error I was asked to post is:
[mehoggan#desktop qsort]$ g++ -o qsort -Wall main.cpp
/tmp/ccuAUzlh.o: In function `Sorters::QuickSorter<float>::test_and_sort(float*, int)':
main.cpp:(.text._ZN7Sorters11QuickSorterIfE13test_and_sortEPfi[Sorters::QuickSorter<float>::test_and_sort(float*, int)]+0x61): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& Sorters::operator<< <float>(std::basic_ostream<char, std::char_traits<char> >&, Sorters::Sorter<float>&)'
collect2: ld returned 1 exit status
[mehoggan#desktop qsort]$
and that is using the following code:
#ifndef SORTERS_H_
#define SORTERS_H_
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <cmath>
#include <ctime>
#include <assert.h>
using std::vector;
using std::cin;
using std::cout;
using std::endl;
using std::ostream_iterator;
using std::istream_iterator;
using std::next_permutation;
using std::back_inserter;
using std::ostream;
namespace Sorters {
template<typename T>
class Sorter {
public:
Sorter( ) { };
virtual ~Sorter( ) { };
virtual void test_and_sort( T *data, int size )=0;
protected:
virtual void sort( typename vector<T>::iterator left, typename vector<T>::iterator right )=0;
vector<T> m_data;
};
template<typename T>
class QuickSorter : public Sorter<T> {
public:
QuickSorter( ) { };
virtual ~QuickSorter( ) { };
virtual void test_and_sort( T *data, int size );
private:
virtual void sort( typename std::vector<T>::iterator left, typename std::vector<T>::iterator right );
template<typename S> friend ostream& operator<< ( ostream &stream, Sorter<S> &sorter );
};
}
template<typename T>
void Sorters::QuickSorter<T>::sort( typename vector<T>::iterator left, typename vector<T>::iterator right ) {
}
template<typename T>
void Sorters::QuickSorter<T>::test_and_sort( T *data, int size ) {
for( int i=0;i<size;i++ ) {
vector<T> perm( &data[0], &data[i+1] );
do {
cout << (*this) << endl;
copy( perm.begin( ),perm.end( ),back_inserter( m_data ) );
this->sort( m_data.begin( ), m_data.end( ) );
} while( next_permutation( perm.begin( ), perm.end( ) ) );
m_data.clear( );
}
}
template<typename S> ostream& operator<< ( ostream &stream, Sorters::Sorter<S> &sorter ) {
copy( sorter->m_data.begin( ),sorter->m_data.end( ), ostream_iterator<S>( stream," " ) );
return stream;
}
#endif
UPDATE
I have written a smaller example so I know my concept works, it just get obfuscated when I use polymorphism and friend functions.
#include <vector>
#include <iostream>
#include <algorithm>
#include <iterator>
using namespace std;
class Sample {
public:
Sample( ) { };
Sample( float *data, int size ) {
copy(&data[0],&data[size],back_inserter( m_data ) );
};
~Sample( ) { };
private:
vector<float> m_data;
friend ostream& operator<< ( ostream &stream, Sample &s ) {
copy( s.m_data.begin( ), s.m_data.end( ), ostream_iterator<float>( stream, " " ) );
return stream;
}
};
int main( int argc, char *argv[] ) {
float data[ ] = {1,2,3,4,5};
Sample s(data,5);
cout << s;
}
SOLUTION
Now to write the actual algorithm. I noticed though if I move m_data up to the parrent class I get compiler errors saying that m_data cannot be found. I guess that just means Insertion Sort, Radix Sort, Stooge Sort, ... will all have there own container.
#ifndef SORTERS_H_
#define SORTERS_H_
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <cmath>
#include <ctime>
#include <assert.h>
using std::vector;
using std::cin;
using std::cout;
using std::endl;
using std::ostream_iterator;
using std::istream_iterator;
using std::next_permutation;
using std::back_inserter;
using std::ostream;
namespace Sorters {
template<typename T>
class Sorter {
public:
Sorter( ) { };
virtual ~Sorter( ) { };
virtual void test_and_sort( T *data, int size )=0;
protected:
virtual void sort( typename vector<T>::iterator left, typename vector<T>::iterator right )=0;
};
template<typename T>
class QuickSorter : public Sorter<T> {
public:
QuickSorter( ) { };
virtual ~QuickSorter( ) { };
virtual void test_and_sort( T *data, int size );
private:
vector<T> m_data;
virtual void sort( typename std::vector<T>::iterator left, typename std::vector<T>::iterator right );
friend ostream& operator<< ( ostream &stream, const QuickSorter &sorter ) {
copy( sorter.m_data.begin( ),sorter.m_data.end( ),ostream_iterator<T>( stream," " ) );
return stream;
}
};
}
template<typename T>
void Sorters::QuickSorter<T>::sort( typename vector<T>::iterator left, typename vector<T>::iterator right ) {
}
template<typename T>
void Sorters::QuickSorter<T>::test_and_sort( T *data, int size ) {
for( int i=0;i<size;i++ ) {
vector<T> perm( &data[0], &data[i+1] );
do {
copy( perm.begin( ),perm.end( ),back_inserter( m_data ) );
cout << (*this) << endl;
this->sort( m_data.begin( ), m_data.end( ) );
m_data.clear( );
} while( next_permutation( perm.begin( ), perm.end( ) ) );
}
}
#endif
First thing that you are printing the address by printing this. You need to print as,
cout << *this << endl;
In the comments you mentioned that you get errors. That's because of following line in operator << ():
vector<S> copy = sorter.m_data; // <--- where is 'm_data' ??
sorter is of type class Sorter<S> and there is no m_data inside it.
To fix this, either move m_data from QuickSorter to Sorter or overload operator << with QuickSorter<S>&.
You’re defining the operator << overload outside the Sorters namespace. That’s an error: you need to define it in the same namespace as the class (first of all, this is where you’ve declared it using the friend declaration; and second of all, this is where argument-dependent loopup is looking for the overload when you use it later on).
Why the code as shown acts the way it does is explained in the comments: cout << this prints a pointer, which results in an address being output. Your operator << overload expects a reference to an object, not a pointer, so it does not get used. As you said, the solution to this is to use cout << *this.
When I make that change, I ended up with a linker error. Somewhere between the templates, and the namespaces, something got confused, and I'm not clear on what. So I did the easy solution: define the function within the class.
Instead of
template<typename T>
struct QuickSorter {
template<typename T> friend ostream& operator <<(ostream&, QuickSorter<T>&);
}
template<typename T>
ostream& operator <<(ostream&, QuickSorter<T>&) { }
I did
template<typename T>
struct QuickSorter {
friend ostream& operator <<(ostream&, QuickSorter&) { }
};
Now, you don't have to worry about getting template parameters right and whatnot. Templated functions have to be declared inline anyhow, so you might as well just do this and get it over with. Note that you also do not declare operator << as a template itself... you are only interested in giving friendship to the one overload, for the specific T the class happens to be using.
Then, you get informed that the function accesses a member m_data, which does not exist in Sorter<T>. This is straight forward: Sorter<T> does not have that member; QuickSorter<T> does. So change the second parameter to the function to QuickSorter<T>& so that the compiler can find that particular member. This change is also reflected above.
The last thing I would do is make the operator overload accept a const QuickSorter<T>& instead of a non-const one. It does not modify the object in any way, so there is no reason not to.
Related
I'm receiving an error code when trying to declare a new stack object that uses a template class. I can't seem to find anything regarding this and most of the questions asked that I've found seem to refer to be for creating functions. Any help on how to resolve this would be greatly appreciated.
#include <stdio.h>
#include <iostream>
#include "stack4.h"
using namespace main_savitch_6B;
using namespace std;
int main(int argc, char **argv)
{
template <class Item> //error: expected expression
stack a;
a.push(4);
return 0;
}
my header file:
#ifndef MAIN_SAVITCH_STACK4_H
#define MAIN_SAVITCH_STACK4_H
#include <cstdlib> // Provides NULL and size_t
#include "node2.h" // Node template class from Figure 6.5 on page 308
namespace main_savitch_6B //7B
{
template <class Item>
class stack
{
public:
// TYPEDEFS
typedef std::size_t size_type;
typedef Item value_type;
// CONSTRUCTORS and DESTRUCTOR
stack( ) { top_ptr = NULL; }
stack(const stack& source);
~stack( ) { list_clear(top_ptr); }
// MODIFICATION MEMBER FUNCTIONS
void push(const Item& entry);
void pop( );
void operator =(const stack& source);
Item& top( );
void swap(stack& y);
// CONSTANT MEMBER FUNCTIONS
size_type size( ) const
{ return main_savitch_6B::list_length(top_ptr); }
bool empty( ) const { return (top_ptr == NULL); }
const Item& top( ) const;
private:
main_savitch_6B::node<Item> *top_ptr; // Points to top of stack
};
}
#include "stack4.template" // Include the implementation
#endif
stack<int> a;
if you want to define an instance of a template class
Commenting out some lines of never executed function definition fixes it though. How come?
Full minimal example I've ended up with while deleting unrelated code below.
int main() {
auto tList = tokenize();
tList.front()->~Token(); //hangs forever if the code 10 lines above is not commented, normally I'll have pop_front() here
cout << "never gets printed";
return 0;
}
Normally I'll have
tList.pop_front()
instead of
tList.front()->~Token();
it's here just to demonstrate it more explicitly
Promised code: (also on https://gist.github.com/anonymous/3b8fa11e90c617b35623ba5432050c3e#file-main-cpp-L68)
tokenizer.h
#include <list>
#include <memory>
using namespace std;
#ifndef SGREP_TOKENIZER_H
#define SGREP_TOKENIZER_H
class Token {
public:
virtual ~Token() = default;
virtual bool isChar() const {
return false;
}
};
using TTokenList = list<unique_ptr<Token>>;
TTokenList tokenize ();
#endif //SGREP_TOKENIZER_H
tokenizer.cpp
#include <iostream>
#include <cctype>
#include <string>
#include "tokenizer.h"
using namespace std;
class Char : public Token {
char value;
public:
Char (char value) : value(value){};
bool isChar() const override {
return true;
}
};
TTokenList tokenize () {
TTokenList tList;
tList.push_back(make_unique<Char>('h'));
return tList;
}
main.cpp
#include <iostream>
#include <string>
#include <vector>
#include <memory>
#include <exception>
#include "tokenizer.h"
using namespace std;
class SyntaxError : public exception {};
class Regex {
public:
virtual size_t match_part(const string& str, size_t begin, size_t maxLen, vector<size_t>& groups) = 0; // groups is a vector of begin,end indices of matched groups (ParenRegexes) (to be able to recreate substrings)
virtual ~Regex() = default;
};
class Char : public Regex {
protected:
vector<char> characterRanges; // pairs -> lower and upper inclusive bound of matching a character (even lower, odd upper), size is always divisible by 2
public:
Char(TTokenList& t, size_t& groupCount) {}
size_t match_part(const string& str, size_t begin, size_t maxLen, vector<size_t>& groups) override {
return 1;
}
};
class SeqRegex: public Regex {
unique_ptr<Regex> a;
public:
SeqRegex(TTokenList& t, size_t& groupCount);
size_t match_part(const string& str, size_t begin, size_t maxLen, vector<size_t>& groups) override { // maxLen by nemelo byt 0:
return 1;
}
};
class OrRegex: public Regex {
SeqRegex a;
public:
OrRegex(TTokenList& t, size_t& groupCount) : a(t, groupCount) {}
size_t match_part(const string& str, size_t begin, size_t maxLen, vector<size_t>& groups) override {
return 1;
}
};
SeqRegex::SeqRegex(TTokenList& t, size_t& groupCount) {
if (t.front()->isChar()) { // Commenting out this portion of code fixes the forever hanging ..
a = make_unique<Char>(t, groupCount);
} else {
cerr << "syntax error, expected [^)]-*^|]" << endl;
throw SyntaxError();
} // ...commenting out up to this point
}
int main() {
auto tList = tokenize();
tList.front()->~Token(); //hangs forever if the code 10 lines above is not commented, normally I'll have pop_front() here
cout << "never gets printed";
return 0;
}
There are, in totality, maybe a dozen unique scenarios where it is appropriate to directly call an object's destructor using the ~T() syntax.
This is no such scenario.
If your intent is to delete the first token in the list, simply calling tList.pop_front() is sufficient.
Calling the destructor directly like you are is going to invoke undefined behavior when the std::unique_ptr object maintaining it later tries to delete it again. So you can't make guarantees about what will or won't happen when this code gets compiled/executed.
You have two classes called Char. They do not have the same definition. This is a violation of the one-definition-rule (ODR) and thus undefined behavior.
I'm just curious why you didn't immediately discover this when you merged the files together.
So I am creating a Stack class for an assignment in C++. The core of the assignment is to familiarize us with templates. I have read my book over and over and looked question after question on here.
I need to have my Stack class be able to be constructed by
Stack s2;
but I get an error when I compile my test.cpp and can only compile when i construct as
Stack<T> s1;
where T is a std::string, int, etc. How do build my Stack so I can use both constructors?
Stack.cpp
#include <iostream>
#include <vector>
#include <stdlib.h>
#include <string>
using namespace std;
template<typename T>
class Stack {
public:
Stack();
void Push(T val);
T Pop();
void Print();
private:
vector<T> vecT;
};
template <typename T>
Stack<T>::Stack() { }
template <typename T>
void Stack<T>::Push(T val) { vecT.push_back(val); }
template <typename T>
T Stack<T>::Pop() { vecT.pop_back(); }
template <typename T>
void Stack<T>::Print() {
cout << "[ ";
for(int i=0; i<vecT.size(); i++) {
cout << vecT[i] << " ";
}
cout << "]";
}
test.cpp
#include <iostream>
#include <vector>
#include <stdlib.h>
#include <string>
#include "Stack.cpp"
using namespace std;
int main() {
Stack<string> s1;
s1.Push("values1");
s1.Push("values2");
s1.Print();
Stack s2;
s2.Push("values1");
s2.Push("values2");
s2.Print();
}
What about a default template parameter?
template<typename T = std::string>
class Stack {
Anyway, with
Stack<T> s1;
and
Stack s2;
you're not using different constructors; you're using, in both cases, the same default (no arguments) constructor.
Instead of templating everything you could just use a stack of a variant type (since C++17, before use Boost.Variant). With the code below you can now push int, double, and std::string onto the stack. Furthermore, Pop() is missing a return statement. Also, pop_back() of vector returns nothing.
#include <iostream>
#include <vector>
#include <string>
#include <variant>
class Stack {
using Variant = std::variant<int,double,std::string>;
public:
Stack();
void Push(Variant val);
void Pop();
void Print();
private:
std::vector<Variant> vecT;
};
Stack::Stack() : vecT() {}
void Stack::Push(Variant val) { vecT.push_back(val); }
void Stack::Pop() { vecT.pop_back(); }
void Stack::Print() {
std::cout << "[ ";
for ( auto const& v : vecT )
std::visit([] (auto&& arg) { std::cout << arg << " "; }, v);
std::cout << "]\n";
}
int main() {
Stack s1;
s1.Push("values1");
s1.Push("values2");
s1.Print();
Stack s2;
s2.Push("values1");
s2.Push("values2");
s2.Print();
}
With Boost.Variant you get a C++98 compatible solution.
#include <iostream>
#include <vector>
#include <string>
#include <boost/variant.hpp>
class Stack {
typedef boost::variant<int,double,std::string> Variant;
typedef std::vector<Variant>::iterator Iterator;
std::vector<Variant> vecT;
struct visitor : public boost::static_visitor<void>
{
template < typename T >
void operator()(T const& arg) const { std::cout << arg << " "; }
};
public:
Stack();
void Push(Variant val);
void Pop();
void Print();
};
Stack::Stack() : vecT() {}
void Stack::Push(Variant val) { vecT.push_back(val); }
void Stack::Pop() { vecT.pop_back(); }
void Stack::Print() {
std::cout << "[ ";
for ( Iterator it = vecT.begin(); it != vecT.end(); ++it )
boost::apply_visitor( visitor(), *it );
std::cout << "]\n";
}
int main() {
Stack s1;
s1.Push("values1");
s1.Push("values2");
s1.Print();
Stack s2;
s2.Push("values1");
s2.Push("values2");
s2.Print();
}
You could use a default template parameter:
template<typename T = int>
class Stack {
Then you could construct using:
Stack<> s2;
Also, the constructors are identical, you aren't calling a different one each time, but rather the template argument differs.
Consider this code snippet:
#include <iostream>
#include <string>
#include <limits>
int main()
{
std::cout << std::numeric_limits<double>::quiet_NaN();
}
When compiled with Visual Studio 2010, output is 1.#QNAN. When compiled with g++, output is nan. Note that Visual Studio 2015 outputs "nan".
However, I need both to produce the same output. What's the most simple way to do that? I tried to override operator<< for double but I feel like that's not the right way to do. Can string to be used for NaN value be forced at stream level, or better, at global level (using std::locale stuff?...never used that...).
I found this squaring_num_put example. Interesting because it's a way to modify a number is redirected to the output. But I'm having a hard time trying to adapt it to my problem (Could not make do_put send either a number or a hard coded "NaN" string to the ostream...).
You might use a stream manipulator or modify the underlying locale:
Manipulator:
#include <cmath>
#include <ostream>
template <typename T>
struct FloatFormat
{
const T value;
FloatFormat(const T& value)
: value(value)
{}
void write(std::ostream& stream) const {
if(std::isnan(value))
stream << "Not a Number";
else
stream << value;
}
};
template <typename T>
inline FloatFormat<T> float_format(const T& value) {
return FloatFormat<T>(value);
}
template <typename T>
inline std::ostream& operator << (std::ostream& stream, const FloatFormat<T>& value) {
value.write(stream);
return stream;
}
int main() {
std::cout << float_format(std::numeric_limits<double>::quiet_NaN()) << '\n';
}
Locale:
#include <cmath>
#include <locale>
#include <ostream>
template<typename Iterator = std::ostreambuf_iterator<char>>
class NumPut : public std::num_put<char, Iterator>
{
private:
using base_type = std::num_put<char, Iterator>;
public:
using char_type = typename base_type::char_type;
using iter_type = typename base_type::iter_type;
NumPut(std::size_t refs = 0)
: base_type(refs)
{}
protected:
virtual iter_type do_put(iter_type out, std::ios_base& str, char_type fill, double v) const override {
if(std::isnan(v))
out = std::copy(std::begin(NotANumber), std::end(NotANumber), out);
else
out = base_type::do_put(out, str, fill, v);
return out;
}
virtual iter_type do_put(iter_type out, std::ios_base& str, char_type fill, long double v) const override {
if(std::isnan(v))
out = std::copy(std::begin(NotANumber), std::end(NotANumber), out);
else
out = base_type::do_put(out, str, fill, v);
return out;
}
private:
static const char NotANumber[];
};
template<typename Iterator>
const char NumPut<Iterator>::NotANumber[] = "Not a Number";
#include <iostream>
#include <limits>
int main() {
#if 1
{
const std::size_t NoDestroy = 1;
NumPut<> num_put(NoDestroy);
std::locale locale(std::cout.getloc(), &num_put);
std::locale restore_locale = std::cin.getloc();
std::cout.imbue(locale);
std::cout << std::numeric_limits<double>::quiet_NaN() << '\n';
// The num_put facet is going out of scope:
std::cout.imbue(restore_locale);
}
#else
{
// Alternitvely use a reference counted facet and pass the ownership to the locales:
auto num_put = new NumPut<>();
std::locale locale(std::cout.getloc(), num_put);
std::cout.imbue(locale);
std::cout << std::numeric_limits<double>::quiet_NaN() << '\n';
}
#endif
std::cout << std::numeric_limits<double>::quiet_NaN() << '\n';
}
Just implement your own checking against the quiet_NaN value, and print based on that.
Derive your YourNumPut from std::num_put.
Override what you need for example: virtual iter_type do_put( iter_type out, std::ios_base& str, char_type fill, double v ) const;
Create locale that uses it: std::locale yourLocale(std::locale(), new YourNumPut());
Set it global, imbue cout and cerr or where you need: std::locale::global(yourLocale); std::cout.imbue(yourLocale); std::cerr.imbue(yourLocale);
Test it
...
Profit ;)
Use isnan() to portably test if a double is a NaN.
#include <cmath>
// ...
double d;
if (isnan(d))
// ...
In C++20 you'll be able to use std::format to do this:
std::cout << std::format("{}", std::numeric_limits<double>::quiet_NaN());
This will print nan on all platforms that have quiet_NaN.
Disclaimer: I'm the author of C++20 std::format.
I have a following problem: I am reusing old code that uses real_p parser to parse real numbers. I would like to capture each number, convert it to string, and put it in vector of strings.
I am using the following code, where l_double is a variable of the type double, convertdouble function converts a double to a string, and result.m_literalValues is the vector of strings.
However, the code will not assign a parsed value to l_double.
rule<> alternative3 = +(real_p [assign_a(l_double)]
[push_back_a(result.m_LiteralValues, convertdouble(l_double))]
>> str_p(",")
)
Does anyone has an idea what am I doing wrong ?
Note: I will not re-engineer the old code, which is much more complex than the example given. I just want to extract the strings of all values parsed, and to put them in the vector of strings.
The problem seems to be located in push_back_a(result.m_LiteralValues, convertdouble(l_double)), specifically in convertdouble(l_double). push_back_a requires that its second argument be a reference to be stored in a "policy holder actor" so using the function call there causes the error. If you don't need to store l_double and were simply using it as a temporary, one way to accomplish what you want is creating your own phoenix function that behaves similarly to push_back_a as explained here(full example here).
You define the phoenix function like this:
struct push_back_impl
{
template <typename Container, typename Item>
struct result
{
typedef void type;
};
template <typename Container, typename Item>
void operator()(Container& c, Item const& item) const
{
c.push_back(convertdouble(item));
}
};
function<push_back_impl> const push_back = push_back_impl();
and then define your rule like this:
rule<> alternative3 = +( real_p[push_back(var(result.m_LiteralValues),arg1)] >> str_p(",") );
Full compilable code(change the for loop to show the results if you can't/don't want to use c++11):
#include <boost/spirit/include/classic_core.hpp>
#include <boost/spirit/include/classic_operators.hpp>
#include <boost/spirit/include/phoenix1_functions.hpp>
#include <boost/spirit/include/phoenix1_primitives.hpp>
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
using namespace boost::spirit::classic;
using namespace phoenix;
std::string convertdouble(const double& d)
{
std::stringstream ss;
ss<<d;
return ss.str();
}
struct push_back_impl
{
template <typename Container, typename Item>
struct result
{
typedef void type;
};
template <typename Container, typename Item>
void operator()(Container& c, Item const& item) const
{
c.push_back(convertdouble(item));
}
};
function<push_back_impl> const push_back = push_back_impl();
struct Results
{
std::vector<std::string> m_LiteralValues;
};
int main()
{
Results result;
char const* test="2.5,3.6,4.8,";
rule<> alternative3 = +( real_p[push_back(var(result.m_LiteralValues),arg1)] >> str_p(",") );
if(parse(test,alternative3,space_p).full)
{
std::cout << "success" << std::endl;
for(auto& str :result.m_LiteralValues)
std::cout << str << std::endl;
}
else
{
std::cout << "failure" << std::endl;
}
return 0;
}