Can not compile a program that uses typeof package by gcc?

Hi, The program below this email does not compile with gcc 4.1.2. g++ (GCC) 4.1.2 20061115 (prerelease) (Debian 4.1.1-21) Copyright (C) 2006 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. I understand that I should ask on the gcc mailing list first, as gcc says it is own bug. But I want to make sure it is not become the typeof package uses some too advanced compiler features. Can somebody let me know if the following code can be compiled by a more recent version of gcc or some other compiler? Thanks, Peng #include <boost/typeof/typeof.hpp> #include <iostream> namespace A { template <typename T> class X { public: X() { } X(T t) : _t(t) { } const T &the_t() const { return _t; } private: T _t; }; template <typename T1, typename T2> struct multiply_traits; template <typename T1, typename T2> struct multiply_traits<X<T1>, T2> { typedef X<T1> result_type; }; template <typename T1, typename T2> typename multiply_traits<X<T1>, T2>::result_type operator*(const X<T1> &x, const T2 &t) { return X<T1>(x.the_t() * t); } } namespace B { template <typename T> class Y { public: Y(T t) : _t(t) { } const T &the_t() const { return _t; } private: T _t; }; template <typename T1, typename T2> //Y<typename multiply_traits<T1, T2>::result_type> operator*(const Y<T1> &y, const T2 &t) { //Y<T1> operator*(const Y<T1> &y, const T2 &t) { Y<BOOST_TYPEOF(T1() * T2())> operator*(const Y<T1> &y, const T2 &t) { return Y<T1>(y.the_t() * t); } } int main () { A::X<int> x(2); B::Y<A::X<int> > y(x); std::cout << (x * 3).the_t() << std::endl; std::cout << (y * 5).the_t().the_t() << std::endl; }

AMDG Peng Yu wrote:
template <typename T1, typename T2> struct multiply_traits;
template <typename T1, typename T2> struct multiply_traits<X<T1>, T2> { typedef X<T1> result_type; };
The most reliable way to define multiply_traits in general is template<class T> T make(); template<class T1, class T2> struct multiply_traits { BOOST_TYPEOF_NESTED_TYPEDEF_TPL(nested, make<T1>() * make<T2>()); typedef typename nested::type type; };
Y<BOOST_TYPEOF(T1() * T2())> operator*(const Y<T1> &y, const T2 &t)
You need to use BOOST_TYPEOF_TPL. http://www.boost.org/doc/libs/1_36_0/doc/html/typeof/refe.html#typeof.typo. Some compilers can handle this (I just tried it on msvc 9.0), but I strongly advise using multiply_traits as defined above for portability. In Christ, Steven Watanabe

On Mon, Oct 20, 2008 at 11:14 AM, Steven Watanabe <watanabesj@gmail.com> wrote:
AMDG
Peng Yu wrote:
template <typename T1, typename T2> struct multiply_traits;
template <typename T1, typename T2> struct multiply_traits<X<T1>, T2> { typedef X<T1> result_type; };
The most reliable way to define multiply_traits in general is
template<class T> T make();
template<class T1, class T2> struct multiply_traits { BOOST_TYPEOF_NESTED_TYPEDEF_TPL(nested, make<T1>() * make<T2>()); typedef typename nested::type type; };
Y<BOOST_TYPEOF(T1() * T2())> operator*(const Y<T1> &y, const T2 &t)
You need to use BOOST_TYPEOF_TPL. http://www.boost.org/doc/libs/1_36_0/doc/html/typeof/refe.html#typeof.typo. Some compilers can handle this (I just tried it on msvc 9.0), but I strongly advise using multiply_traits as defined above for portability.
Does this mean the error that I saw is not due to a GCC bug? Or it is due to a GCC bug, but most other compilers would have the same bug so that I have to use your way as a walkaround? Thanks, Peng

AMDG Peng Yu wrote:
You need to use BOOST_TYPEOF_TPL. http://www.boost.org/doc/libs/1_36_0/doc/html/typeof/refe.html#typeof.typo. Some compilers can handle this (I just tried it on msvc 9.0), but I strongly advise using multiply_traits as defined above for portability.
Does this mean the error that I saw is not due to a GCC bug? Or it is due to a GCC bug, but most other compilers would have the same bug so that I have to use your way as a walkaround?
It is due to a gcc bug, but other compilers have their own bugs. By portability, I meant practical portability, in so far as using multiply_traits works on a lot more compilers. In Christ, Steven Watanabe

On Mon, Oct 20, 2008 at 11:33 AM, Steven Watanabe <watanabesj@gmail.com> wrote:
AMDG
What does AMDG? Does it mean this http://www.geocities.com/thetropics/7177/amdg.htm? Or it means something else?
Peng Yu wrote:
You need to use BOOST_TYPEOF_TPL.
http://www.boost.org/doc/libs/1_36_0/doc/html/typeof/refe.html#typeof.typo. Some compilers can handle this (I just tried it on msvc 9.0), but I strongly advise using multiply_traits as defined above for portability.
Does this mean the error that I saw is not due to a GCC bug? Or it is due to a GCC bug, but most other compilers would have the same bug so that I have to use your way as a walkaround?
It is due to a gcc bug, but other compilers have their own bugs. By portability, I meant practical portability, in so far as using multiply_traits works on a lot more compilers.
I see. Does the fact that BOOST_TYPEOF are BOOST_TYPEOF_TPL are there means that they will be eventually the only macros are used, and all the others macros in typeof package will be unnecessary and discarded when compilers become free of this kind of bug in the future? Thanks, Peng

AMDG Peng Yu wrote:
What does AMDG? Does it mean this http://www.geocities.com/thetropics/7177/amdg.htm?
Yes.
It is due to a gcc bug, but other compilers have their own bugs. By portability, I meant practical portability, in so far as using multiply_traits works on a lot more compilers.
I see. Does the fact that BOOST_TYPEOF are BOOST_TYPEOF_TPL are there means that they will be eventually the only macros are used, and all the others macros in typeof package will be unnecessary and discarded when compilers become free of this kind of bug in the future?
In the future, we will have decltype, so the entire library will become obsolete, although, I expect it to be be kept around for backwards compatibility for a while. In Christ, Steven Watanabe

On Mon, Oct 20, 2008 at 11:14 AM, Steven Watanabe <watanabesj@gmail.com> wrote:
AMDG
Peng Yu wrote:
template <typename T1, typename T2> struct multiply_traits;
template <typename T1, typename T2> struct multiply_traits<X<T1>, T2> { typedef X<T1> result_type; };
The most reliable way to define multiply_traits in general is
template<class T> T make();
template<class T1, class T2> struct multiply_traits { BOOST_TYPEOF_NESTED_TYPEDEF_TPL(nested, make<T1>() * make<T2>()); typedef typename nested::type type; };
Y<BOOST_TYPEOF(T1() * T2())> operator*(const Y<T1> &y, const T2 &t)
You need to use BOOST_TYPEOF_TPL. http://www.boost.org/doc/libs/1_36_0/doc/html/typeof/refe.html#typeof.typo. Some compilers can handle this (I just tried it on msvc 9.0), but I strongly advise using multiply_traits as defined above for portability.
I changed the code according to you message (see below this message). I got the following error, would you please help me figure out what was wrong? main.cc: In instantiation of 'A::multiply_traits<A::X<int>, int>::nested': main.cc:32: instantiated from 'A::multiply_traits<A::X<int>, int>' main.cc:65: instantiated from here main.cc:31: error: no match for 'operator*' in 'A::make [with T = A::X<int>]() * A::make [with T = int]()' main.cc: In function 'int main()': main.cc:65: error: no match for 'operator*' in 'x * 3' main.cc:66: error: no match for 'operator*' in 'A::X<int>() * 0' main.cc:66: error: no match for 'operator*' in 'y * 5' make: *** [main-g.o] Error 1 Thanks, Peng #include <boost/typeof/typeof.hpp> #include <iostream> namespace A { template <typename T> class X { public: X() { } X(T t) : _t(t) { } const T &the_t() const { return _t; } private: T _t; }; template <typename T1, typename T2> struct multiply_traits; #if 0 template <typename T1, typename T2> struct multiply_traits<X<T1>, T2> { typedef X<T1> result_type; }; #endif template<class T> T make(); template<class T1, class T2> struct multiply_traits { BOOST_TYPEOF_NESTED_TYPEDEF_TPL(nested, make<T1>() * make<T2>()) typedef typename nested::type type; }; template <typename T1, typename T2> typename multiply_traits<X<T1>, T2>::result_type operator*(const X<T1> &x, const T2 &t) { return X<T1>(x.the_t() * t); } } namespace B { template <typename T> class Y { public: Y(T t) : _t(t) { } const T &the_t() const { return _t; } private: T _t; }; template <typename T1, typename T2> //Y<typename multiply_traits<T1, T2>::result_type> operator*(const Y<T1> &y, const T2 &t) { //Y<T1> operator*(const Y<T1> &y, const T2 &t) { Y<BOOST_TYPEOF_TPL(T1() * T2())> operator*(const Y<T1> &y, const T2 &t) { return Y<T1>(y.the_t() * t); } } int main () { A::X<int> x(2); B::Y<A::X<int> > y(x); std::cout << (x * 3).the_t() << std::endl; std::cout << (y * 5).the_t().the_t() << std::endl; }

AMDG Peng Yu wrote:
main.cc: In instantiation of 'A::multiply_traits<A::X<int>, int>::nested': main.cc:32: instantiated from 'A::multiply_traits<A::X<int>, int>' main.cc:65: instantiated from here main.cc:31: error: no match for 'operator*' in 'A::make [with T = A::X<int>]() * A::make [with T = int]()' main.cc: In function 'int main()': main.cc:65: error: no match for 'operator*' in 'x * 3' main.cc:66: error: no match for 'operator*' in 'A::X<int>() * 0' main.cc:66: error: no match for 'operator*' in 'y * 5' make: *** [main-g.o] Error 1
template<class T1, class T2> struct multiply_traits { BOOST_TYPEOF_NESTED_TYPEDEF_TPL(nested, make<T1>() * make<T2>()) typedef typename nested::type type; };
template <typename T1, typename T2> typename multiply_traits<X<T1>, T2>::result_type operator*(const X<T1> &x, const T2 &t) { return X<T1>(x.the_t() * t); }
}
Note that the operator* deduces it's return type from multiply_traits, and multiply_traits in turn uses the result of operator*. You need to either specialize multiply_traits for X. (The specialization you #if'ed out should work fine). Or you can change operator*: template<class T1, class T2> X<T1> operator*(const X<T1> &x, const T2 &t); Also, I made a mistake, multiply_traits should say typedef typedef nested::type result_type; instead of typedef ... type;. In Christ, Steven Watanabe

On Mon, Oct 20, 2008 at 11:38 AM, Steven Watanabe <watanabesj@gmail.com> wrote:
AMDG
Peng Yu wrote:
main.cc: In instantiation of 'A::multiply_traits<A::X<int>, int>::nested': main.cc:32: instantiated from 'A::multiply_traits<A::X<int>, int>' main.cc:65: instantiated from here main.cc:31: error: no match for 'operator*' in 'A::make [with T = A::X<int>]() * A::make [with T = int]()' main.cc: In function 'int main()': main.cc:65: error: no match for 'operator*' in 'x * 3' main.cc:66: error: no match for 'operator*' in 'A::X<int>() * 0' main.cc:66: error: no match for 'operator*' in 'y * 5' make: *** [main-g.o] Error 1
template<class T1, class T2> struct multiply_traits { BOOST_TYPEOF_NESTED_TYPEDEF_TPL(nested, make<T1>() * make<T2>()) typedef typename nested::type type; };
template <typename T1, typename T2> typename multiply_traits<X<T1>, T2>::result_type operator*(const X<T1> &x, const T2 &t) { return X<T1>(x.the_t() * t); }
}
Note that the operator* deduces it's return type from multiply_traits, and multiply_traits in turn uses the result of operator*. You need to either specialize multiply_traits for X. (The specialization you #if'ed out should work fine). Or you can change operator*:
template<class T1, class T2> X<T1> operator*(const X<T1> &x, const T2 &t);
Also, I made a mistake, multiply_traits should say typedef typedef nested::type result_type; instead of typedef ... type;.
I'm not sure if I understand you correctly. But I got the following code which still ends up with the compiler bug. Would you please give me a complete working copy of the program so that I can play with it? Thanks, Peng #include <boost/typeof/typeof.hpp> #include <iostream> namespace A { template <typename T> class X { public: X() { } X(T t) : _t(t) { } const T &the_t() const { return _t; } private: T _t; }; template <typename T1, typename T2> struct multiply_traits; template <typename T1, typename T2> struct multiply_traits<X<T1>, T2> { typedef X<T1> result_type; }; template <typename T1, typename T2> typename multiply_traits<X<T1>, T2>::result_type operator*(const X<T1> &x, const T2 &t) { return X<T1>(x.the_t() * t); } template<class T> T make(); template<class T1, class T2> struct multiply_traits { BOOST_TYPEOF_NESTED_TYPEDEF_TPL(nested, make<T1>() * make<T2>()) typedef typename nested::type type; }; } namespace B { template <typename T> class Y { public: Y(T t) : _t(t) { } const T &the_t() const { return _t; } private: T _t; }; template <typename T1, typename T2> //Y<typename multiply_traits<T1, T2>::result_type> operator*(const Y<T1> &y, const T2 &t) { //Y<T1> operator*(const Y<T1> &y, const T2 &t) { Y<BOOST_TYPEOF_TPL(T1() * T2())> operator*(const Y<T1> &y, const T2 &t) { return Y<T1>(y.the_t() * t); } } int main () { A::X<int> x(2); B::Y<A::X<int> > y(x); std::cout << (x * 3).the_t() << std::endl; std::cout << (y * 5).the_t().the_t() << std::endl; }

AMDG Peng Yu wrote:
I'm not sure if I understand you correctly. But I got the following code which still ends up with the compiler bug. Would you please give me a complete working copy of the program so that I can play with it?
attached. In Christ, Steven Watanabe

On Mon, Oct 20, 2008 at 11:57 AM, Steven Watanabe <watanabesj@gmail.com> wrote:
AMDG
Peng Yu wrote:
I'm not sure if I understand you correctly. But I got the following code which still ends up with the compiler bug. Would you please give me a complete working copy of the program so that I can play with it?
attached.
Hi, In line 51-55 of you attached file, it says the following. template <typename T1, typename T2> Y<typename A::multiply_traits<T1, T2>::result_type> operator*(const Y<T1> &y, const T2 &t) { return Y<T1>(y.the_t() * t); } This way requires that I have to explicitly say 'multiply_traits' is from the namespace A. I wanted to use the following instead, which does not need to specify which the namespaces T1 and T2 are. But the following code still results in the compiler error. template <typename T1, typename T2> Y<BOOST_TYPEOF(T1() * T2())> operator*(const Y<T1> &y, const T2 &t) { return Y<T1>(y.the_t() * t); } My question is not resolved. I'm attaching the source file with some comments to avoid any confusion. Would you please take another look at the problem? Thanks, Peng

On Mon, Oct 20, 2008 at 2:35 PM, Peng Yu <pengyu.ut@gmail.com> wrote:
On Mon, Oct 20, 2008 at 11:57 AM, Steven Watanabe <watanabesj@gmail.com> wrote:
AMDG
Peng Yu wrote:
I'm not sure if I understand you correctly. But I got the following code which still ends up with the compiler bug. Would you please give me a complete working copy of the program so that I can play with it?
attached.
Hi,
In line 51-55 of you attached file, it says the following.
template <typename T1, typename T2> Y<typename A::multiply_traits<T1, T2>::result_type> operator*(const Y<T1> &y, const T2 &t) { return Y<T1>(y.the_t() * t); }
This way requires that I have to explicitly say 'multiply_traits' is from the namespace A. I wanted to use the following instead, which does not need to specify which the namespaces T1 and T2 are. But the following code still results in the compiler error.
template <typename T1, typename T2> Y<BOOST_TYPEOF(T1() * T2())> operator*(const Y<T1> &y, const T2 &t) { return Y<T1>(y.the_t() * t); }
My question is not resolved. I'm attaching the source file with some comments to avoid any confusion. Would you please take another look at the problem?
Here is the correct file. Thanks, Peng

AMDG Peng Yu wrote:
In line 51-55 of you attached file, it says the following.
template <typename T1, typename T2> Y<typename A::multiply_traits<T1, T2>::result_type> operator*(const Y<T1> &y, const T2 &t) { return Y<T1>(y.the_t() * t); }
This way requires that I have to explicitly say 'multiply_traits' is from the namespace A. I wanted to use the following instead, which does not need to specify which the namespaces T1 and T2 are. But the following code still results in the compiler error.
template <typename T1, typename T2> Y<BOOST_TYPEOF(T1() * T2())> operator*(const Y<T1> &y, const T2 &t) { return Y<T1>(y.the_t() * t); }
My question is not resolved. I'm attaching the source file with some comments to avoid any confusion. Would you please take another look at the problem?
Alright. If you don't want to refer to multiply_traits from namespace A, then put a generic multiply_traits somewhere else. When it is defined using Boost.Typeof, it will work for any types. It does not matter what namespace multiply_traits is defined in. Really. template<class T1, class T2> struct typeof_multiply { BOOST_TYPEOF_NESTED_TYPEDEF_TPL(nested, (make<T1>() * make<T2>())); typedef typename nested::type type; }; ... template<class T1, class T2> Y<typename typeof_multiply<T1, T2>::type> operator*(...); Really, all this does is to move the typeof calculation into a separate metafunction. In Christ, Steven Watanabe

On Mon, Oct 20, 2008 at 10:19 PM, Steven Watanabe <watanabesj@gmail.com> wrote:
AMDG
Peng Yu wrote:
In line 51-55 of you attached file, it says the following.
template <typename T1, typename T2> Y<typename A::multiply_traits<T1, T2>::result_type> operator*(const Y<T1> &y, const T2 &t) { return Y<T1>(y.the_t() * t); }
This way requires that I have to explicitly say 'multiply_traits' is from the namespace A. I wanted to use the following instead, which does not need to specify which the namespaces T1 and T2 are. But the following code still results in the compiler error.
template <typename T1, typename T2> Y<BOOST_TYPEOF(T1() * T2())> operator*(const Y<T1> &y, const T2 &t) { return Y<T1>(y.the_t() * t); }
My question is not resolved. I'm attaching the source file with some comments to avoid any confusion. Would you please take another look at the problem?
Alright. If you don't want to refer to multiply_traits from namespace A, then put a generic multiply_traits somewhere else. When it is defined using Boost.Typeof, it will work for any types. It does not matter what namespace multiply_traits is defined in. Really.
This is a reasonable solution. But no matter which namespace multiply_traits puts, it pollutes that namespace. Since namespace is a way to better organized the code, I'd rather multiply_traits be in the same namespace as that of its associated types. Since Koenig lookup can be used to deduce the namespace of a function based on whether its arugments are from, I'm wondering why C++ does not allow such look up for templates? If Koenig lookup can be used for template, then the problem is solved. Thanks, Peng

AMDG Peng Yu wrote:
This is a reasonable solution. But no matter which namespace multiply_traits puts, it pollutes that namespace. Since namespace is a way to better organized the code, I'd rather multiply_traits be in the same namespace as that of its associated types.
A generic multiply_traits is not tied to any specific type. You can always put it in a detail namespace.
Since Koenig lookup can be used to deduce the namespace of a function based on whether its arugments are from, I'm wondering why C++ does not allow such look up for templates? If Koenig lookup can be used for template, then the problem is solved.
That would cause worse problems. Koenig lookup can cause obscure, hard to find bugs in generic code, when the wrong function is called. In Christ, Steven Watanabe

A generic multiply_traits is not tied to any specific type. You can always put it in a detail namespace.
Suppose everything in B of my original code is from a library called B. Other codes are for the use of library B. Do you mean that all multiply_traits shall be defined in a namespace such as B::detail? When new classes X1, X2, ... are defined, I need to define the corresponding multiply_traits in B::detail. If the library B (with namespace B) is designed such that nothing is defined in namespace B::detail, then the users can define whatever they want in B::detail, as there would be no conflicting between their code and the library code, right? Thanks, Peng

AMDG Peng Yu wrote:
A generic multiply_traits is not tied to any specific type. You can always put it in a detail namespace.
Suppose everything in B of my original code is from a library called B. Other codes are for the use of library B.
Do you mean that all multiply_traits shall be defined in a namespace such as B::detail?
Yes. In template libraries you often need namespace scope helper classes and functions that should not be visible to the user.
When new classes X1, X2, ... are defined, I need to define the corresponding multiply_traits in B::detail. If the library B (with namespace B) is designed such that nothing is defined in namespace B::detail, then the users can define whatever they want in B::detail, as there would be no conflicting between their code and the library code, right?
They could, in that the language does not forbid it, but I would consider it a bad idea to put user code in a namespace nested within a library's namespace. In Christ, Steven Watanabe

Do you mean that all multiply_traits shall be defined in a namespace such as B::detail?
Yes. In template libraries you often need namespace scope helper classes and functions that should not be visible to the user.
I'm confused. You agreed above that multiply_traits shall be defined in B::detail. Down below, you said that it's better not to put user defined code in B::detail, while multiply_traits corresponding to X1, X2,..., are user defined code. Then where do I need to put multiply_traits?
When new classes X1, X2, ... are defined, I need to define the corresponding multiply_traits in B::detail. If the library B (with namespace B) is designed such that nothing is defined in namespace B::detail, then the users can define whatever they want in B::detail, as there would be no conflicting between their code and the library code, right?
They could, in that the language does not forbid it, but I would consider it a bad idea to put user code in a namespace nested within a library's namespace.

AMDG Peng Yu wrote:
I'm confused. You agreed above that multiply_traits shall be defined in B::detail. Down below, you said that it's better not to put user defined code in B::detail, while multiply_traits corresponding to X1, X2,..., are user defined code.
Then where do I need to put multiply_traits?
What I meant to say was that if library B contains a function that needs to deduce the result type of a multiplication, then it should put a typeof based multiply_traits in B::detail. It doesn't matter what X1, X2, etc are because Boost.Typeof handles the actual deduction. If you have a different multiply_traits for every type, then it is completely useless in generic code. In Christ, Steven Watanabe

On Wed, Oct 22, 2008 at 4:28 PM, Steven Watanabe <watanabesj@gmail.com> wrote:
AMDG
Peng Yu wrote:
I'm confused. You agreed above that multiply_traits shall be defined in B::detail. Down below, you said that it's better not to put user defined code in B::detail, while multiply_traits corresponding to X1, X2,..., are user defined code.
Then where do I need to put multiply_traits?
What I meant to say was that if library B contains a function that needs to deduce the result type of a multiplication, then it should put a typeof based multiply_traits in B::detail.
It doesn't matter what X1, X2, etc are because Boost.Typeof handles the actual deduction.
BOOST_TYPEOF does not work with the current version of GCC, the compiler that I use. That is why I have to use multiply_traits. Then where I put multiply_traits?
If you have a different multiply_traits for every type, then it is completely useless in generic code.
I don't quite understand what you mean. Since users have their choice to define whatever classes to be used of B::Y, they have to have a way to define multiply_traits if they want. I don't understand why "it is completely useless in generic code". What you mean by generic code? Essentially, I want see if there is a solution or a walkaround to the question posted at http://groups.google.com/group/comp.lang.c++.moderated/browse_thread/thread/... Would you please read it if my original question was not quite clear to you? Thanks, Peng

AMDG Peng Yu wrote:
What I meant to say was that if library B contains a function that needs to deduce the result type of a multiplication, then it should put a typeof based multiply_traits in B::detail.
BOOST_TYPEOF does not work with the current version of GCC, the compiler that I use. That is why I have to use multiply_traits. Then where I put multiply_traits?
Boost.Typeof *does* work on gcc--as long as you don't try to use it in a function signature.
If you have a different multiply_traits for every type, then it is completely useless in generic code.
I don't quite understand what you mean. Since users have their choice to define whatever classes to be used of B::Y, they have to have a way to define multiply_traits if they want. I don't understand why "it is completely useless in generic code". What you mean by generic code?
By generic code I mean any template that wants to take two arbitrary types, multiply instances of them together, and find the result type. If you have two separate multiply_traits in different namespaces, then as far as the compiler is concerned, they are two completely separate entities. The compiler resolves which multiply_traits is used when the template using it is defined. It is impossible to dispatch based on the namespace of the template arguments. In Christ, Steven Watanabe

On Wed, Oct 22, 2008 at 9:01 PM, Steven Watanabe <watanabesj@gmail.com> wrote:
AMDG
Peng Yu wrote:
What I meant to say was that if library B contains a function that needs to deduce the result type of a multiplication, then it should put a typeof based multiply_traits in B::detail.
BOOST_TYPEOF does not work with the current version of GCC, the compiler that I use. That is why I have to use multiply_traits. Then where I put multiply_traits?
Boost.Typeof *does* work on gcc--as long as you don't try to use it in a function signature.
Because of a bug in GCC, BOOST_TYPEOF (which essentially is a macro for 'typeof') does not work for the attached code. I tried GCC 4.1.1, somebody else tried GCC 4.3.0. Neither of them work for the attached code.
If you have a different multiply_traits for every type, then it is completely useless in generic code.
I don't quite understand what you mean. Since users have their choice to define whatever classes to be used of B::Y, they have to have a way to define multiply_traits if they want. I don't understand why "it is completely useless in generic code". What you mean by generic code?
By generic code I mean any template that wants to take two arbitrary types, multiply instances of them together, and find the result type.
If you have two separate multiply_traits in different namespaces, then as far as the compiler is concerned, they are two completely separate entities. The compiler resolves which multiply_traits is used when the template using it is defined. It is impossible to dispatch based on the namespace of the template arguments.
Since BOOST_TYPEOF is does not work for the attached code, then I'll have to define multiply_traits for user defined types, X1, X2, in the namespace of B::detail. This is not a prefect solution. But it is probably the most satisfiable solution based on the constraints that we have. Thanks, Peng

AMDG Peng Yu wrote:
Because of a bug in GCC, BOOST_TYPEOF (which essentially is a macro for 'typeof') does not work for the attached code. I tried GCC 4.1.1, somebody else tried GCC 4.3.0. Neither of them work for the attached code.
What attached code? In Christ, Steven Watanabe

On Wed, Oct 22, 2008 at 9:28 PM, Steven Watanabe <watanabesj@gmail.com> wrote:
AMDG
Peng Yu wrote:
Because of a bug in GCC, BOOST_TYPEOF (which essentially is a macro for 'typeof') does not work for the attached code. I tried GCC 4.1.1, somebody else tried GCC 4.3.0. Neither of them work for the attached code.
What attached code?
Sorry, I forgot to attach the code. Here is the attached code. Thanks, Peng

Peng Yu:
On Wed, Oct 22, 2008 at 9:28 PM, Steven Watanabe <watanabesj@gmail.com> wrote:
AMDG
Peng Yu wrote:
Because of a bug in GCC, BOOST_TYPEOF (which essentially is a macro for 'typeof') does not work for the attached code. I tried GCC 4.1.1, somebody else tried GCC 4.3.0. Neither of them work for the attached code.
What attached code?
Sorry, I forgot to attach the code. Here is the attached code.
This is not what Steven meant. It was probably the use of the term "traits" that threw you away. multiply_traits is not a traits class; it's just an implementation detail that places a level of indirection between typeof and the signature. Wherever you need to use BOOST_TYPEOF( T1() * T2() ) in a function signature, you replace it with typename multiply_helper<T1,T2>::type where template<class T1, class T2> struct multiply_helper { typedef BOOST_TYPEOF( T1() * T2() ) type; }; Nobody specializes multiply_helper. It just moves the typeof a bit to satisfy the compiler. The underlying reason for all this dance is that compilers cannot mangle an arbitrary expression into a function name, and typeof allows one to put arbitrary expressions in signatures. -- Peter Dimov http://www.pdplayer.com
participants (3)
-
Peng Yu
-
Peter Dimov
-
Steven Watanabe