Hello, at the moment I want to make a getter function for a tuple type. The tuple is internally hidden in a class. For that I want to make a function which returns the values inside the tuple. The best solution would be if I can make a enum which defines the position inside the tuple and a template function which returns the value for this tuple. I have tested the following, but it doesn't work: typedef struct Members { enum Member { name = 0, value = 1, }; }Members; template<enum Member member> element<0, Properties::Property>::type name()(const boost::tuples::tuple<std::wstring, boost::any>& prop) { return boost::tuples::get<member>(prop); } Can anyone give my an hint? I'm not very familiar with the metaprogramming things... Best regards Hansjörg
Hansi wrote:
Hello,
at the moment I want to make a getter function for a tuple type. The tuple is internally hidden in a class. For that I want to make a function which returns the values inside the tuple. The best solution would be if I can make a enum which defines the position inside the tuple and a template function which returns the value for this tuple.
I have tested the following, but it doesn't work:
typedef struct Members { enum Member { name = 0, value = 1, }; }Members;
template<enum Member member> element<0, Properties::Property>::type name()(const boost::tuples::tuple<std::wstring, boost::any>& prop) { return boost::tuples::get<member>(prop); }
I didn't quite understand your goals here so I implemented both I thought you could mean: #include <boost/tuple/tuple.hpp> #include <string> #include <iostream> template < typename T1, typename T2 > struct Test { typedef boost::tuple<T1,T2> tuple_t; tuple_t tup; enum Members { NAME, VALUE }; typename boost::tuples::element<NAME, tuple_t>::type name() { return tup.get<NAME>(); } template < Members mem > typename boost::tuples::element<mem, tuple_t>::type member() { return tup.get<mem>(); } }; int main() { Test<std::string, int> t; t.tup = Test<std::string,int>::tuple_t("Test", 42); std::cout << t.name() << std::endl; std::cout << t.member<Test<std::string,int>::VALUE>() << std::endl; std::cin.get(); } Get the metaprogramming book by Abrahams and Gurtovoy. It's completely necessary to understand metaprogramming to be able to use these aspects of boost.
Noah Roberts schrieb:
Hansi wrote:
Hello,
at the moment I want to make a getter function for a tuple type. The tuple is internally hidden in a class. For that I want to make a function which returns the values inside the tuple. The best solution would be if I can make a enum which defines the position inside the tuple and a template function which returns the value for this tuple.
I have tested the following, but it doesn't work:
typedef struct Members { enum Member { name = 0, value = 1, }; }Members;
template<enum Member member> element<0, Properties::Property>::type name()(const boost::tuples::tuple<std::wstring, boost::any>& prop) { return boost::tuples::get<member>(prop); }
I didn't quite understand your goals here so I implemented both I thought you could mean:
#include <boost/tuple/tuple.hpp> #include <string> #include <iostream>
template < typename T1, typename T2 > struct Test { typedef boost::tuple<T1,T2> tuple_t; tuple_t tup;
enum Members { NAME, VALUE };
typename boost::tuples::element<NAME, tuple_t>::type name() { return tup.get<NAME>(); }
this version doesn't work with my compiler (msvc8.0). I get the error: error C2899:typename cannot be used outside a template declaration But this would be the preferred version for me. Have you an idea how I can solve this? Best regards Hansjörg
template < Members mem > typename boost::tuples::element<mem, tuple_t>::type member() { return tup.get<mem>(); } };
int main() { Test<std::string, int> t; t.tup = Test<std::string,int>::tuple_t("Test", 42);
std::cout << t.name() << std::endl; std::cout << t.member<Test<std::string,int>::VALUE>() << std::endl;
std::cin.get(); }
Get the metaprogramming book by Abrahams and Gurtovoy. It's completely necessary to understand metaprogramming to be able to use these aspects of boost.
Hansi wrote:
Noah Roberts schrieb:
Hansi wrote:
Hello,
at the moment I want to make a getter function for a tuple type. The tuple is internally hidden in a class. For that I want to make a function which returns the values inside the tuple. The best solution would be if I can make a enum which defines the position inside the tuple and a template function which returns the value for this tuple.
I have tested the following, but it doesn't work:
typedef struct Members { enum Member { name = 0, value = 1, }; }Members;
template<enum Member member> element<0, Properties::Property>::type name()(const boost::tuples::tuple<std::wstring, boost::any>& prop) { return boost::tuples::get<member>(prop); }
I didn't quite understand your goals here so I implemented both I thought you could mean:
#include <boost/tuple/tuple.hpp> #include <string> #include <iostream>
template < typename T1, typename T2 > struct Test { typedef boost::tuple<T1,T2> tuple_t; tuple_t tup;
enum Members { NAME, VALUE };
typename boost::tuples::element<NAME, tuple_t>::type name() { return tup.get<NAME>(); }
this version doesn't work with my compiler (msvc8.0). I get the error:
error C2899:typename cannot be used outside a template declaration
But this would be the preferred version for me. Have you an idea how I can solve this?
This is a compiler error and should be reported as such. Even in C++03 the usage of typename is not limited to *dependent* names (although it must only occur in a template context), see [temp.res]/5: "[..] The keyword typename shall be applied only to qualified names, but those names need not be dependent. The keyword typename shall be used only in contexts in which dependent names can be used. This includes template declarations and definitions but excludes explicit specialization declarations and explicit instantiation declarations.[..]" Greetings from Bremen, Daniel Krügler
Am Mittwoch 21 Mai 2008 08:42:34 schrieb Hansi:
Noah Roberts schrieb:
#include <boost/tuple/tuple.hpp> #include <string> #include <iostream>
template < typename T1, typename T2 > struct Test { typedef boost::tuple<T1,T2> tuple_t; tuple_t tup;
enum Members { NAME, VALUE };
typename boost::tuples::element<NAME, tuple_t>::type name() { return tup.get<NAME>(); }
This code is almost correct :o) . Try the attached File.
this version doesn't work with my compiler (msvc8.0). I get the error:
error C2899:typename cannot be used outside a template declaration
But this would be the preferred version for me. Have you an idea how I can solve this?
Best, -- Maik
This code is almost correct :o) . Try the attached File. Now you missed one "typename": template < Members mem >
_________________________________________________________________ News, entertainment and everything you care about at Live.com. Get it now! http://www.live.com/getstarted.aspx
Sorry, I just didn't read the code correctly.
This code is almost correct :o) . Try the attached File.> >> > Now you missed one "typename": template < Members mem >> > ??> > Please state the complete statement you refer to.> > -- Maik
Invite your mail contacts to join your friends list with Windows Live Spaces. It's easy! http://spaces.live.com/spacesapi.aspx?wx_action=create&wx_url=/friends.aspx&mkt=en-us
Okay this version is working. The problem is that I have a fixed defined tuple and for that the tuple is not defined inside a template struct. for that I get the error that typename can be used only inside a template declaration... I have something similar to the following declaration: struct Test { typedef boost::tuple<int,char> tuple_t; tuple_t tup; enum Members { NAME, VALUE }; typename boost::tuples::element<NAME, tuple_t>::type name() { return boost::get<NAME>(tup); } template < Members mem > typename boost::tuples::element<mem, tuple_t>::type member() { return boost::get<mem>(tup); } }; Maik Beckmann schrieb:
Am Mittwoch 21 Mai 2008 08:42:34 schrieb Hansi:
Noah Roberts schrieb:
#include <boost/tuple/tuple.hpp> #include <string> #include <iostream>
template < typename T1, typename T2 > struct Test { typedef boost::tuple<T1,T2> tuple_t; tuple_t tup;
enum Members { NAME, VALUE };
typename boost::tuples::element<NAME, tuple_t>::type name() { return tup.get<NAME>(); }
This code is almost correct :o) . Try the attached File.
this version doesn't work with my compiler (msvc8.0). I get the error:
error C2899:typename cannot be used outside a template declaration
But this would be the preferred version for me. Have you an idea how I can solve this?
Best, -- Maik
------------------------------------------------------------------------
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
Am Mittwoch 21 Mai 2008 10:55:53 schrieb Hansi:
Okay this version is working. The problem is that I have a fixed defined tuple and for that the tuple is not defined inside a template struct. for that I get the error that typename can be used only inside a template declaration...
The compiler is right, omit the typename keyword if you're not inside a template. In this case you can even write tup.get<enumFoo>() instead of tup.template get<enumFoo>() The good thing about this syntax get<Whatever>(tup) is, it work always, inside a template or not. -- Maik
Maik Beckmann wrote:
Am Mittwoch 21 Mai 2008 10:55:53 schrieb Hansi:
Okay this version is working. The problem is that I have a fixed defined tuple and for that the tuple is not defined inside a template struct. for that I get the error that typename can be used only inside a template declaration...
The compiler is right, omit the typename keyword if you're not inside a template. In this case you can even write tup.get<enumFoo>() instead of tup.template get<enumFoo>()
Should I have had that in my function? The compiler didn't bitch about it not being there... I also test my code before posting to lists and such unless otherwise expressed. The code I originally posted compiled and worked just fine. Can you cite chapter and verse why it shouldn't have? I try to be as standard compliant as I can.
On Wed, May 21, 2008 at 12:22 PM, Noah Roberts <roberts.noah@gmail.com> wrote:
Maik Beckmann wrote:
The compiler is right, omit the typename keyword if you're not inside a template. In this case you can even write tup.get<enumFoo>() instead of tup.template get<enumFoo>()
Should I have had that in my function? The compiler didn't bitch about it not being there...
I also test my code before posting to lists and such unless otherwise expressed. The code I originally posted compiled and worked just fine. Can you cite chapter and verse why it shouldn't have? I try to be as standard compliant as I can.
http://www.comeaucomputing.com/techtalk/templates/#templateprefix --Michael Fawcett
Hansi wrote:
Noah Roberts schrieb:
Hello,
at the moment I want to make a getter function for a tuple type. The tuple is internally hidden in a class. For that I want to make a function which returns the values inside the tuple. The best solution would be if I can make a enum which defines the position inside the tuple and a template function which returns the value for this tuple.
I have tested the following, but it doesn't work:
typedef struct Members { enum Member { name = 0, value = 1, }; }Members;
template<enum Member member> element<0, Properties::Property>::type name()(const boost::tuples::tuple<std::wstring, boost::any>& prop) { return boost::tuples::get<member>(prop); } I didn't quite understand your goals here so I implemented both I
Hansi wrote: thought you could mean:
#include <boost/tuple/tuple.hpp> #include <string> #include <iostream>
template < typename T1, typename T2 > struct Test { typedef boost::tuple<T1,T2> tuple_t; tuple_t tup;
enum Members { NAME, VALUE };
typename boost::tuples::element<NAME, tuple_t>::type name() { return tup.get<NAME>(); }
this version doesn't work with my compiler (msvc8.0). I get the error:
error C2899:typename cannot be used outside a template declaration
But this would be the preferred version for me. Have you an idea how I can solve this?
That's exactly the compiler I used to compile this code. Have you altered it in some way? The typename keyword is quite specifically needed in the above code, but would be quite specifically disallowed with some minor differences, namely if the "Test" class was not templated or if the tuple type was not dependent on any of the template parameters. Try to just create a new project and copy/paste my code into it, replacing their non-standard main function with the one I have. You'll probably need to keep the "stdafx.h" include. What version of boost? I have 1.34 on this system; we have not upgraded yet as our products will adversely affected by changes to some libraries and we're not yet prepared to deal with that. I have a feeling though that you tried to integrate my code into your particular problem without first testing mine. You may very well not need the 'typename' keyword. I would suggest really studying when and where to use that keyword if that's the case for it is fundamental to understanding templates and is not the easiest thing in the world to learn.
Hello, Thank you for your helped. You was right. I have tested your code inside mine. For that I have adapted something and the problem (I have posted it in another answer). The problem ist that I had the follwing struct: struct Test { typedef boost::tuple<int,char> tuple_t; tuple_t tup; enum Members { NAME, VALUE }; typename boost::tuples::element<NAME, tuple_t>::type name() { return boost::get<NAME>(tup); } }; and here the declaration doesn't work. I use boost 1.34.1 Thank you very much Hansjörg Noah Roberts schrieb:
Hansi wrote:
Hello,
at the moment I want to make a getter function for a tuple type. The tuple is internally hidden in a class. For that I want to make a function which returns the values inside the tuple. The best solution would be if I can make a enum which defines the position inside the tuple and a template function which returns the value for this tuple.
I have tested the following, but it doesn't work:
typedef struct Members { enum Member { name = 0, value = 1, }; }Members;
template<enum Member member> element<0, Properties::Property>::type name()(const boost::tuples::tuple<std::wstring, boost::any>& prop) { return boost::tuples::get<member>(prop); } I didn't quite understand your goals here so I implemented both I
Hansi wrote: thought you could mean:
#include <boost/tuple/tuple.hpp> #include <string> #include <iostream>
template < typename T1, typename T2 > struct Test { typedef boost::tuple<T1,T2> tuple_t; tuple_t tup;
enum Members { NAME, VALUE };
typename boost::tuples::element<NAME, tuple_t>::type name() { return tup.get<NAME>(); }
Noah Roberts schrieb: this version doesn't work with my compiler (msvc8.0). I get the error:
error C2899:typename cannot be used outside a template declaration
But this would be the preferred version for me. Have you an idea how I can solve this?
That's exactly the compiler I used to compile this code. Have you altered it in some way? The typename keyword is quite specifically needed in the above code, but would be quite specifically disallowed with some minor differences, namely if the "Test" class was not templated or if the tuple type was not dependent on any of the template parameters.
Try to just create a new project and copy/paste my code into it, replacing their non-standard main function with the one I have. You'll probably need to keep the "stdafx.h" include.
What version of boost? I have 1.34 on this system; we have not upgraded yet as our products will adversely affected by changes to some libraries and we're not yet prepared to deal with that.
I have a feeling though that you tried to integrate my code into your particular problem without first testing mine. You may very well not need the 'typename' keyword. I would suggest really studying when and where to use that keyword if that's the case for it is fundamental to understanding templates and is not the easiest thing in the world to learn.
Hansi wrote:
Hello,
Thank you for your helped. You was right. I have tested your code inside mine. For that I have adapted something and the problem (I have posted it in another answer). The problem ist that I had the follwing struct:
struct Test { typedef boost::tuple<int,char> tuple_t; tuple_t tup; enum Members { NAME, VALUE };
typename boost::tuples::element<NAME, tuple_t>::type name() { return boost::get<NAME>(tup); } };
and here the declaration doesn't work.
loose the typename. I read what others stated about its appropriateness and I don't know if that is true or not. What I do know is that the compiler we both use won't accept it. If you remove typename it should work.
Noah Roberts wrote:
Hansi wrote:
Hello,
Thank you for your helped. You was right. I have tested your code inside mine. For that I have adapted something and the problem (I have posted it in another answer). The problem ist that I had the follwing struct:
struct Test { typedef boost::tuple<int,char> tuple_t; tuple_t tup; enum Members { NAME, VALUE };
typename boost::tuples::element<NAME, tuple_t>::type name() { return boost::get<NAME>(tup); } };
and here the declaration doesn't work.
loose the typename. I read what others stated about its appropriateness and I don't know if that is true or not. What I do know is that the compiler we both use won't accept it.
If you remove typename it should work.
I totally agree with you, the typename here - at least what is visible from this snippet context - is not legal according to C++03, see [temp.res], 5: "The keyword typename shall only be used in template declarations and definitions, including in the return type of a function template or member function template, in the return type for the definition of a member function of a class template or of a class nested within a class template, and in the type-specifier for the definition of a static member of a class template or of a class nested within a class template." Concerning the opinion of others: My original reply suggesting that the compiler is broken was related to a different code, which started with a template context like this: template < typename T1, typename T2 > struct Test { typedef boost::tuple<T1,T2> tuple_t; tuple_t tup; enum Members { NAME, VALUE }; typename boost::tuples::element<NAME, tuple_t>::type name() { ... } }; The typename in front of boost::tuples::element is legal and it is *required* in this case. My original posting overlooked that the arguments of the relevant template were dependent, but the answer was still correct, because the important point is that the typename is legal in a template context, even if the corresponding name is *not* dependent. So this example is legal as well: #include <utility> template <typename> struct TT { typename std::pair<int, double>::first_type name() { return 0; } }; int main() { return TT<void>().name(); } If the compiler does not accept the typename here, it is broken, which was the essence of my OP. Greetings from Bremen, Daniel Krügler
Daniel Krügler wrote:
#include <utility>
template <typename> struct TT { typename std::pair<int, double>::first_type name() { return 0; } };
int main() { return TT<void>().name(); }
If the compiler does not accept the typename here, it is broken, which was the essence of my OP.
I see. Yeah, it was a bit hard to track what was going on with the OP's code.
Yes this works! thanks Noah Roberts schrieb:
Hansi wrote:
Hello,
Thank you for your helped. You was right. I have tested your code inside mine. For that I have adapted something and the problem (I have posted it in another answer). The problem ist that I had the follwing struct:
struct Test { typedef boost::tuple<int,char> tuple_t; tuple_t tup; enum Members { NAME, VALUE };
typename boost::tuples::element<NAME, tuple_t>::type name() { return boost::get<NAME>(tup); } };
and here the declaration doesn't work.
loose the typename. I read what others stated about its appropriateness and I don't know if that is true or not. What I do know is that the compiler we both use won't accept it.
If you remove typename it should work.
Hi,
struct Test { typedef boost::tuple<int,char> tuple_t; tuple_t tup; enum Members { NAME, VALUE };
typename boost::tuples::element<NAME, tuple_t>::type name() { return boost::get<NAME>(tup); } };
why not simple derive: struct Test : boost::tuple<int,char> { enum Members { NAME, VALUE }; }; Than you have the tuple calling syntax: get<Test::Name>( ... ) That's what I use for reading and writing "named" tuples. Regards, Olaf
Olaf Peter wrote:
why not simple derive:
struct Test : boost::tuple<int,char> { enum Members { NAME, VALUE }; };
Than you have the tuple calling syntax:
get<Test::Name>( ... )
That's what I use for reading and writing "named" tuples.
How useful have people found this technique? I started using tuples for simple data structures and did such a thing. I found that it added more syntatic complexity than was of benefit; that simply creating a data store class/POD was the easier, clearer method.
I mean the version tup.get<NAME>(); Regarding to microsoft The typename keyword can be used only in a template definition or declaration. In a template declaration, it can be used in two ways: // C2899b.cpp // compile with: /c struct Y { typedef int B; typename Y::B b; // C2899 }; Best regards Hansjörg Maik Beckmann schrieb:
Am Dienstag 20 Mai 2008 18:43:28 schrieb Noah Roberts:
tup.get<NAME>();
tup.get<mem>();
Did you mean boost::get<NAME>(tup); boost::get<mem>(tup); ??
-- Maik
participants (7)
-
Daniel Krügler
-
Hansi
-
Igor R.
-
Maik Beckmann
-
Michael Fawcett
-
Noah Roberts
-
Olaf Peter