[boost-users][proto] Types of arguments to operator()

I realize that this may be more of a C++ language question rather than
proto specific. But I will ask it anyway. I wrote a transform that
infers some type information for the placeholders from an expression.
Say I have the expression _1 = _2 + 1, the transform can tell me that
the type of the first argument to operator() of the expression wrapper
should be "T &" and the type of the second should be "const T&". Here
is the transform (thanks to JoelF for his help on this) :
struct arg_tag {};
template<int N>
struct arg
: proto::or_
{};
namespace boost { namespace proto {
template<class T> struct is_callable< readonly<T> > : mpl::true_ {};
template<class T> struct is_callable< readwrite<T> > : mpl::true_ {};
} }
Now, given an expression type E, I can say "typename
boost::result_of

On 5/7/2010 10:55 AM, Manjunath Kudlur wrote:
Now, given an expression type E, I can say "typename boost::result_of
(const E &)>::type" and it will be either "T0 &" or "const T0 &" depending on how _1 appears in the expression E. Using this, I tried to write an expression wrapper with operator() overloaded as follows : template<typename T0> void operator()(typename boost::result_of
(const Expr &)>::type arg0) const { cout << "arg0 " << arg0 << "\n"; } But the compiler fails to find a match with this overloaded version when I write, say, (_1)(10). Is it some fundamental C++ restriction that causes this, or am I missing something?
There's a fundamental restriction. T0 is in a nondeduced context here.
Imagine a template Int like:
template<typename T> struct Int { typedef int type; };
and used like
template<typename T>
void foo(typename Int<T>::type) ...
foo(1);
What can the compiler say about T? Any choice will work, so the compiler
has no way to pick one.
What you need to do instead is define both const and non-const overloads
and either use SFINAE to get one to drop out, or else (better, IMO)
assert within the function that the correct one has been chosen:
template<typename T0>
void operator()(T0 & arg0) const
{
BOOST_MPL_ASSERT((
is_same<
T0 &,
typename boost::result_of

On Fri, May 7, 2010 at 11:10 AM, Eric Niebler
On 5/7/2010 10:55 AM, Manjunath Kudlur wrote:
Now, given an expression type E, I can say "typename boost::result_of
(const E &)>::type" and it will be either "T0 &" or "const T0 &" depending on how _1 appears in the expression E. Using this, I tried to write an expression wrapper with operator() overloaded as follows : template<typename T0> void operator()(typename boost::result_of
(const Expr &)>::type arg0) const { cout << "arg0 " << arg0 << "\n"; } But the compiler fails to find a match with this overloaded version when I write, say, (_1)(10). Is it some fundamental C++ restriction that causes this, or am I missing something?
There's a fundamental restriction. T0 is in a nondeduced context here. Imagine a template Int like:
template<typename T> struct Int { typedef int type; };
and used like
template<typename T> void foo(typename Int<T>::type) ...
foo(1);
What can the compiler say about T? Any choice will work, so the compiler has no way to pick one.
Thanks for the quick response and the nice explanation.
What you need to do instead is define both const and non-const overloads and either use SFINAE to get one to drop out, or else (better, IMO) assert within the function that the correct one has been chosen:
That would work, except that I would need 2^n versions for operator() taking 'n' arguments. (Yay! I discovered the perfect forwarding problem all by myself :-/). -- Manjunath http://nonchalantlytyped.net/blog/musings/

On 5/7/2010 11:26 AM, Manjunath Kudlur wrote:
That would work, except that I would need 2^n versions for operator() taking 'n' arguments. (Yay! I discovered the perfect forwarding problem all by myself :-/).
Yep, congrats. -- Eric Niebler BoostPro Computing http://www.boostpro.com

On Fri, May 7, 2010 at 12:09 PM, Eric Niebler
On 5/7/2010 11:26 AM, Manjunath Kudlur wrote:
That would work, except that I would need 2^n versions for operator() taking 'n' arguments. (Yay! I discovered the perfect forwarding problem all by myself :-/).
Yep, congrats.
BTW, can you give a heads-up on how this is going to be solved in Phoenix3? -- Manjunath http://nonchalantlytyped.net/blog/musings/

Manjunath Kudlur wrote:
BTW, can you give a heads-up on how this is going to be solved in Phoenix3?
Good question. I guess we'll use the functional::forward in C++98 and has a #if(BOOSt_HAS_RVALUES) version with rvalue references. Nothing clear yet on this point -- ___________________________________________ Joel Falcou - Assistant Professor PARALL Team - LRI - Universite Paris Sud XI Tel : (+33)1 69 15 66 35

On 5/7/2010 12:40 PM, joel falcou wrote:
Manjunath Kudlur wrote:
BTW, can you give a heads-up on how this is going to be solved in Phoenix3?
Good question. I guess we'll use the functional::forward in C++98 and has a #if(BOOSt_HAS_RVALUES) version with rvalue references. Nothing clear yet on this point
I think the plan is to capture by value by default and require special syntax to capture by reference. That side-steps the issue. -- Eric Niebler BoostPro Computing http://www.boostpro.com

Eric Niebler wrote:
I think the plan is to capture by value by default and require special syntax to capture by reference. That side-steps the issue.
Also works ;) -- ___________________________________________ Joel Falcou - Assistant Professor PARALL Team - LRI - Universite Paris Sud XI Tel : (+33)1 69 15 66 35

Manjunath Kudlur schrieb:
On Fri, May 7, 2010 at 12:09 PM, Eric Niebler
wrote: On 5/7/2010 11:26 AM, Manjunath Kudlur wrote:
That would work, except that I would need 2^n versions for operator() taking 'n' arguments. (Yay! I discovered the perfect forwarding problem all by myself :-/).
Yep, congrats.
BTW, can you give a heads-up on how this is going to be solved in Phoenix3?
It might help you. If you take a look in the proto example folder, you will find the file lambda.hpp. There the 2^n operators overloads are created using preprocessor meta programming. Very cool. -Kim
-- Manjunath http://nonchalantlytyped.net/blog/musings/ _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
participants (4)
-
Eric Niebler
-
joel falcou
-
Kim Kuen Tang
-
Manjunath Kudlur