-
September 23rd, 2009, 01:56 PM
#1
Boost tuple and Vector problem
Hi everyone!
I'm doing a test to try and improve my understanding of vectors and boost tuples and am having the following problem.
I have simplified the issue down to the code pasted below and am working with:
- MS Visual C++ 2008
- Boost library 1.38
Aim
- I want to create a vector of tuple<int, double> elements and pass it by reference to a method/template to populate it.
At the moment in the populate method I can create the tuple element and insert it into a vector also created in the method, but I cannot insert the tuple into the vector which has been passed to the method by reference.
Notes
- I cannot change any of the code in main(), I can only write code in the populateData method.
- Not other fancy libraries etc
Error
- The error occurs in the tuple_basic.hpp and I have included it below (cut the length of it but important info is there)
Any help or info would be appreciated!!
Thanks!!!
Code Start===============================================================
#include "stdafx.h"
#include <vector>
#include <iostream>
#include <string>
#include <sstream>
#include <numeric>
#include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_io.hpp>
template <typename CONTAINER>
void populateData(CONTAINER& container, size_t count)
{
typedef boost::tuple<int, double> row1_t;
std::vector<row1_t> myVect;
for(size_t i=0 ; i<count ; i++)
{
intTuple tempTuple((int(i)));
myVect.push_back(tempTuple);
row1_t myTuple((int(i)), (double(i))/10);
myVect.push_back(myTuple); //This works!
container.push_back(myTuple); //THIS IS THE PROBLEM LINE
};
};
int main()
{
typedef boost::tuple<int, double> row1_t;
typedef std::vector<row1_t> vec1_t;
vec1_t vec1;
populateData(vec1, 100);
TEST_REQUIRE_EQUAL(vec1.size(), 100);
TEST_CHECK_EQUAL_AS_STR(vec1[1],"(1 0.1)");
TEST_CHECK_EQUAL_AS_STR(vec1[99],"(99 9.9)");
}
Code End================================================================
Full Error:
1>------ Build started: Project: wintonExpertTest, Configuration: Debug Win32 ------
1>Compiling...
1>wintonExpertTest.cpp
1>c:\program files\boost\boost_1_38\boost\tuple\detail\tuple_basic.hpp(373) : error C2039: 'tail' : is not a member of 'boost::tuples::cons<HT,TT>'
1> with
1> [
1> HT=double,
1> TT=boost::tuples:etail::map_tuple_to_cons<boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type>::type
1> ]
-
September 23rd, 2009, 03:02 PM
#2
Re: Boost tuple and Vector problem
c:\program files\boost\boost_1_38\boost\tuple\detail\tuple_basic.hpp(373) : error C2039: 'tail' : is not a member of 'boost::tuples::cons<HT,TT>'
On which line this error is occurring? I don't think this error pops up at your commented (//THIS IS THE PROBLEM LINE) part.
You may need to typedef at global level, as compiler may see two typedefs as having different types.
-
September 23rd, 2009, 03:25 PM
#3
Re: Boost tuple and Vector problem
Originally Posted by Ajay Vijay
On which line this error is occurring? I don't think this error pops up at your commented (//THIS IS THE PROBLEM LINE) part.
You may need to typedef at global level, as compiler may see two typedefs as having different types.
The error is caused when I add the line with tthe comment "THIS IS THE LINE THAT CAUSES THE PROBLEM. The error refers to a line in the tuple_basic.hpp file which I assume is not really at fault. The area of code in tuple_basic.hpp that is pointed to by the error is:
template <class HT2, class TT2>
cons( const cons<HT2, TT2>& u ) : head(u.head), tail(u.tail) {}
help!
-
September 23rd, 2009, 09:18 PM
#4
Re: Boost tuple and Vector problem
Originally Posted by MisterEd
The error is caused when I add the line with tthe comment "THIS IS THE LINE THAT CAUSES THE PROBLEM.
The code does not compile for me due to you not posting the actual code you're compiling.
There is no "intTuple" defined, and neither do those macros in main() exist.
Please post the actual code, and use code tags when posting (your code is unformatted and hard to read).
The following compiles and links fine with Visual Studio 2008 SP1 and boost version 1.39.
Code:
#include "stdafx.h"
#include <vector>
#include <iostream>
#include <string>
#include <sstream>
#include <numeric>
#include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_io.hpp>
template <typename CONTAINER>
void populateData(CONTAINER& container, size_t count)
{
typedef boost::tuple<int, double> row1_t;
std::vector<row1_t> myVect;
for(size_t i=0 ; i<count ; i++)
{
row1_t myTuple((int(i)), (double(i))/10);
myVect.push_back(myTuple); //This works!
container.push_back(myTuple); //THIS IS THE PROBLEM LINE
}
}
int main()
{
typedef boost::tuple<int, double> row1_t;
typedef std::vector<row1_t> vec1_t;
vec1_t vec1;
populateData(vec1, 100);
}
Regards,
Paul McKenzie
-
September 23rd, 2009, 09:39 PM
#5
Re: Boost tuple and Vector problem
Hi Paul, thanks for the reply.
I've included the full code below and I think there are two questions I have
1 - Why doesn't this compile when I try and insert the tuple into the vector which is passed to the template function? If I create a vector in the template function then I am able to insert the tuple into it without a problem.
2 - What is the best way to approach this whole problem? (it later uses the template to deal with three element tuples.
Also I note that using push_back may not be the best idea and that I should perhaps use functions common to all containers. I was really just trying things and having a play about in order to become more familiar with tuples and vectors
Thanks again for your help and here is the code:
Code:
#include "stdafx.h"
#include <vector>
#include <iostream>
#include <string>
#include <sstream>
#include <numeric>
#include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_io.hpp>
typedef boost::tuple<int, double> row1_t;
static bool testFailure(false);
static size_t testCount(0);
#define TEST_REQUIRE_EQUAL(a, b) \
{ \
++testCount; \
if (a != b) { \
std::cout << "ERROR: TEST ABORTING (" #a " != " #b ")" << std::endl; \
exit(1); \
} \
}
#define TEST_CHECK_EQUAL(a, b) \
{ \
++testCount; \
if (a != b) { \
std::cout << "ERROR: TEST FAILURE (" #a " != " #b ")" << std::endl; \
testFailure=true; \
} \
}
#define TEST_CHECK_EQUAL_AS_STR(a, b) \
{ \
++testCount; \
std::stringstream lhs, rhs; \
lhs << a; \
rhs << b; \
if (lhs.str() != rhs.str()) { \
std::cout << "ERROR: TEST FAILURE (" \
<< lhs.str() \
<< " != " \
<< rhs.str() \
<< ")" \
<< std::endl \
; \
testFailure=true; \
} \
}
template <typename CONTAINER>
void populateData(CONTAINER& container, size_t count)
{
typedef boost::tuple<int, double> row1_t;
std::vector<row1_t> intDoubTupleVect;
for(size_t i=0 ; i<count ; i++)
{
row1_t anIntDoubTuple((int(i)), (double(i))/10);
intDoubTupleVect.push_back(anIntDoubTuple);
container.push_back(anIntDoubTuple); //This is causing problems
};
}
template<typename ITERATOR_TYPE>
typename ITERATOR_TYPE::value_type sum(const ITERATOR_TYPE& first, const ITERATOR_TYPE& last)
{
typedef typename ITERATOR_TYPE::value_type value_type;
value_type count(static_cast<value_type>(std::distance(first,last)));
if(count==0)
throw std::exception("Cannot calculate the sum of empty series.");
return std::accumulate(first, last, value_type(), std::plus<value_type>());
}
template<typename ITERATOR_TYPE>
typename ITERATOR_TYPE::value_type mean(const ITERATOR_TYPE& first, const ITERATOR_TYPE& last)
{
typedef typename ITERATOR_TYPE::value_type value_type;
value_type count(static_cast<value_type>(std::distance(first,last)));
return sum(first, last)/count;
}
template<typename CONTAINER>
typename CONTAINER::value_type mean(const CONTAINER& container)
{
return mean(container.begin(), container.end());
}
int main()
{
// challenge 1 - pass the following tests
typedef boost::tuple<int, double> row1_t;
typedef std::vector<row1_t> vec1_t;
vec1_t vec1;
populateData(vec1, 100);
TEST_REQUIRE_EQUAL(vec1.size(), 100);
TEST_CHECK_EQUAL_AS_STR(vec1[1],"(1 0.1)");
TEST_CHECK_EQUAL_AS_STR(vec1[99],"(99 9.9)");
typedef boost::tuple<int, double, double> row2_t;
typedef std::vector<row2_t> vec2_t;
vec2_t vec2;
populateData(vec2, 100);
TEST_REQUIRE_EQUAL(vec2.size(), 100);
TEST_CHECK_EQUAL_AS_STR(vec2[1],"(1 0.1 0.01)");
TEST_CHECK_EQUAL_AS_STR(vec2[99],"(99 9.9 0.99)");
// challenge 2 - create a specialisation for strings
// typedef boost::tuple<int, double, std::string> row3_t;
// typedef std::vector<row3_t> vec3_t;
// vec3_t vec3;
// populateData(vec3, 100);
// TEST_REQUIRE_EQUAL(vec3.size(), 100);
// TEST_CHECK_EQUAL_AS_STR(vec3[1],"(1 0.1 1/100)");
// TEST_CHECK_EQUAL_AS_STR(vec3[99],"(99 9.9 99/100)");
// challenge 3 - create a generalised view on the series - ideal solution should not copy data
//TEST_CHECK_EQUAL_AS_STR( mean(columnViewOfTuple<0>(vec1)), 49);
//TEST_CHECK_EQUAL_AS_STR( mean(columnViewOfTuple<1>(vec1)), 4.95);
//TEST_CHECK_EQUAL_AS_STR( mean(columnViewOfTuple<0>(vec2)), 49);
//TEST_CHECK_EQUAL_AS_STR( mean(columnViewOfTuple<1>(vec2)), 4.95);
//TEST_CHECK_EQUAL_AS_STR( mean(columnViewOfTuple<2>(vec2)), 0.495);
//TEST_CHECK_EQUAL_AS_STR( mean(columnViewOfTuple<0>(vec3)), 49);
//TEST_CHECK_EQUAL_AS_STR( mean(columnViewOfTuple<1>(vec3)), 4.95);
TEST_CHECK_EQUAL_AS_STR(testCount, 17);
if (!testFailure) {
std::cout << "Congratulations!\n";
}
}
-
September 24th, 2009, 12:01 AM
#6
Re: Boost tuple and Vector problem
What ever it is you are doing, I fail to understand the reason as to why is it that you are declaring the tuple typedef every time in your PopulateData() and Main() functions???
Code:
typedef boost::tuple<int, double> row1_t
I have not read your code past the line where the problem occurs, but once you make a global declaration, why do u make copies of the same?
Regards,
Bhushan
-
September 24th, 2009, 09:39 AM
#7
Re: Boost tuple and Vector problem
Originally Posted by bhushan1980
What ever it is you are doing, I fail to understand the reason as to why is it that you are declaring the tuple typedef every time in your PopulateData() and Main() functions???
Code:
typedef boost::tuple<int, double> row1_t
I have not read your code past the line where the problem occurs, but once you make a global declaration, why do u make copies of the same?
Regards,
Bhushan
The typedef is given in main() which I do not want to change... and I can't use the typedef declared in main from the function.
So what should I do if I don't want to change the given code in main()?
-
September 24th, 2009, 09:43 AM
#8
Re: Boost tuple and Vector problem
^^ the global declaration shouldn't really be there but I think the main issue I'm having is how to approach the whole exercise/problem
-
September 24th, 2009, 01:14 PM
#9
Re: Boost tuple and Vector problem
this is your problem:
Code:
typedef boost::tuple<int, double, double> row2_t;
typedef std::vector<row2_t> vec2_t;
vec2_t vec2;
populateData(vec2, 100);
Code:
template <typename CONTAINER>
void populateData(CONTAINER& container, size_t count)
{
typedef boost::tuple<int, double> row1_t;
std::vector<row1_t> intDoubTupleVect;
for(size_t i=0 ; i<count ; i++)
{
row1_t anIntDoubTuple((int(i)), (double(i))/10);
intDoubTupleVect.push_back(anIntDoubTuple);
container.push_back(anIntDoubTuple); //This is causing problems
};
}
-
September 28th, 2009, 01:24 PM
#10
Re: Boost tuple and Vector problem
Firstly, thanks for everyone's help so far! So here's my code now.
Code:
#include "stdafx.h"
#include <vector>
#include <iostream>
#include <string>
#include <sstream>
#include <numeric>
#include <boost/lexical_cast.hpp> //MR Added to cast from double to string
#include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_io.hpp>
static bool testFailure(false);
static size_t testCount(0);
#define TEST_REQUIRE_EQUAL(a, b) \
{ \
++testCount; \
if (a != b) { \
std::cout << "ERROR: TEST ABORTING (" #a " != " #b ")" << std::endl; \
exit(1); \
} \
}
#define TEST_CHECK_EQUAL(a, b) \
{ \
++testCount; \
if (a != b) { \
std::cout << "ERROR: TEST FAILURE (" #a " != " #b ")" << std::endl; \
testFailure=true; \
} \
}
#define TEST_CHECK_EQUAL_AS_STR(a, b) \
{ \
++testCount; \
std::stringstream lhs, rhs; \
lhs << a; \
rhs << b; \
if (lhs.str() != rhs.str()) { \
std::cout << "ERROR: TEST FAILURE (" \
<< lhs.str() \
<< " != " \
<< rhs.str() \
<< ")" \
<< std::endl \
; \
testFailure=true; \
} \
}
//Function for challenge 1, for when recursion hits last tuple element
inline void set_to_val_over_ten(const boost::tuples::null_type&, double){};
//Challenge 1 - populates tuple recursively
template<typename H, typename T>
inline void set_to_val_over_ten(boost::tuples::cons<H, T>& x, double V )
{
x.get_head() = V;
set_to_val_over_ten(x.get_tail(), V/10);
}
//Challenge 2 - specialisation for strings
template< typename T>
inline void set_to_val_over_ten(boost::tuples::cons<std::string, T>& x, double V )
{
x.get_head() = boost::lexical_cast<std::string>(V);
set_to_val_over_ten(x.get_tail(), V/10);
}
//Challenge 1 - Provided function template
template <typename CONTAINER>
void populateData(CONTAINER& container, size_t count)
{
for(size_t i=0 ; i<count ; i++)
{
typename CONTAINER::value_type tupleToAdd(i);
set_to_val_over_ten(tupleToAdd.get_tail(), double(i)/10.0);
container.push_back(tupleToAdd);
};
}
template<typename ITERATOR_TYPE>
typename ITERATOR_TYPE::value_type sum(const ITERATOR_TYPE& first, const ITERATOR_TYPE& last)
{
typedef typename ITERATOR_TYPE::value_type value_type;
value_type count(static_cast<value_type>(std::distance(first,last)));
if(count==0)
throw std::exception("Cannot calculate the sum of empty series.");
return std::accumulate(first, last, value_type(), std::plus<value_type>());
}
template<typename ITERATOR_TYPE>
typename ITERATOR_TYPE::value_type mean(const ITERATOR_TYPE& first, const ITERATOR_TYPE& last)
{
typedef typename ITERATOR_TYPE::value_type value_type;
value_type count(static_cast<value_type>(std::distance(first,last)));
return sum(first, last)/count;
}
template<typename CONTAINER>
typename CONTAINER::value_type mean(const CONTAINER& container)
{
return mean(container.begin(), container.end());
}
int main()
{
// challenge 1 - pass the following tests
typedef boost::tuple<int, double> row1_t;
typedef std::vector<row1_t> vec1_t;
vec1_t vec1;
populateData(vec1, 100);
TEST_REQUIRE_EQUAL(vec1.size(), 100);
TEST_CHECK_EQUAL_AS_STR(vec1[1],"(1 0.1)");
TEST_CHECK_EQUAL_AS_STR(vec1[99],"(99 9.9)");
typedef boost::tuple<int, double, double> row2_t;
typedef std::vector<row2_t> vec2_t;
vec2_t vec2;
populateData(vec2, 100);
TEST_REQUIRE_EQUAL(vec2.size(), 100);
TEST_CHECK_EQUAL_AS_STR(vec2[1],"(1 0.1 0.01)");
TEST_CHECK_EQUAL_AS_STR(vec2[99],"(99 9.9 0.99)");
// challenge 2 - create a specialisation for strings
typedef boost::tuple<int, double, std::string> row3_t;
typedef std::vector<row3_t> vec3_t;
vec3_t vec3;
populateData(vec3, 100);
TEST_REQUIRE_EQUAL(vec3.size(), 100);
TEST_CHECK_EQUAL_AS_STR(vec3[1],"(1 0.1 1/100)");
TEST_CHECK_EQUAL_AS_STR(vec3[99],"(99 9.9 99/100)");
// challenge 3 - create a generalised view on the series - ideal solution should not copy data
//TEST_CHECK_EQUAL_AS_STR( mean(columnViewOfTuple<0>(vec1)), 49);
//TEST_CHECK_EQUAL_AS_STR( mean(columnViewOfTuple<1>(vec1)), 4.95);
//TEST_CHECK_EQUAL_AS_STR( mean(columnViewOfTuple<0>(vec2)), 49);
//TEST_CHECK_EQUAL_AS_STR( mean(columnViewOfTuple<1>(vec2)), 4.95);
//TEST_CHECK_EQUAL_AS_STR( mean(columnViewOfTuple<2>(vec2)), 0.495);
//TEST_CHECK_EQUAL_AS_STR( mean(columnViewOfTuple<0>(vec3)), 49);
//TEST_CHECK_EQUAL_AS_STR( mean(columnViewOfTuple<1>(vec3)), 4.95);
TEST_CHECK_EQUAL_AS_STR(testCount, 17);
if (!testFailure) {
std::cout << "Congratulations!\n";
}
}
The problem I'm now having is when main() calls the following line in challenge 2
Code:
TEST_CHECK_EQUAL_AS_STR(vec3[1],"(1 0.1 1/100)");
I've made the mistake of just changing the double to a string instead of a fraction such as "1/100" by using the boost lexical cast.
While I could change the template function to unclude the vector element number currently being iterated
(In the above case this would give the numerator) and also pass in the tuple element number being
iterated through (10^ this number would give the denominator).
I'm fairly sure there must be a more elegant way of doing this?
Any ideas please?
Tags for this Thread
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|