CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 10 of 10
  1. #1
    Join Date
    Sep 2009
    Posts
    19

    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> ]

  2. #2
    Join Date
    Mar 2003
    Location
    India {Mumbai};
    Posts
    3,871

    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.
    My latest article: Explicating the new C++ standard (C++0x)

    Do rate the posts you find useful.

  3. #3
    Join Date
    Sep 2009
    Posts
    19

    Re: Boost tuple and Vector problem

    Quote Originally Posted by Ajay Vijay View Post
    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!

  4. #4
    Join Date
    Apr 1999
    Posts
    27,449

    Re: Boost tuple and Vector problem

    Quote Originally Posted by MisterEd View Post
    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

  5. #5
    Join Date
    Sep 2009
    Posts
    19

    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";
    	}
    
    }

  6. #6
    Join Date
    Jun 2006
    Posts
    645

    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

  7. #7
    Join Date
    Sep 2009
    Posts
    19

    Re: Boost tuple and Vector problem

    Quote Originally Posted by bhushan1980 View Post
    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()?

  8. #8
    Join Date
    Sep 2009
    Posts
    19

    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

  9. #9
    Join Date
    Apr 2008
    Posts
    725

    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
    	};
    
    }

  10. #10
    Join Date
    Sep 2009
    Posts
    19

    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
  •  





Click Here to Expand Forum to Full Width

Featured