views:

165

answers:

3

Hi, I have the following code:

template <typename T> LuaCall& operator>>(T) { BOOST_STATIC_ASSERT(sizeof(T) == 0); }
template <> LuaCall& operator>><int&>(int& val) { mResults.push_back(std::make_pair(LUA_RESULT_INTEGER, (void *)&val)); return *this; }
template <> LuaCall& operator>><float&>(float& val) { mResults.push_back(std::make_pair(LUA_RESULT_FLOAT, (void *)&val)); return *this; }
template <> LuaCall& operator>><double&>(double& val) { mResults.push_back(std::make_pair(LUA_RESULT_DOUBLE, (void *)&val)); return *this; }
template <> LuaCall& operator>><bool&>(bool& val) { mResults.push_back(std::make_pair(LUA_RESULT_BOOLEAN, (void *)&val)); return *this; }
template <> LuaCall& operator>><std::string&>(std::string& val) { mResults.push_back(std::make_pair(LUA_RESULT_STRING, (void *)&val)); return *this; }
template <> LuaCall& operator>><LuaNilStruct>(LuaNilStruct) { mResults.push_back(std::make_pair(LUA_RESULT_NIL, (void *)NULL)); return *this; }

And then:

int abc;
LuaCall(l, "test") % "test" % 5 % LuaNil % 2.333 >> abc;

I want it to work kinda like cin >> does, ie it needs to write to abc the return value of the lua function. So I need its address.. but it defaults on the default template. What am I doing wrong? There is surely a way to do this since cin does exactly that.

Thanks!


Note to whoever changed the %'s to >>: I changed it back since it's the way it is :D The code calls the Lua function test("test", 5, nil, 2.333) and saves its return value to abc. %'s are for the parameters of the functions, >>'s are for the return value(s).

template <typename T>
LuaCall& operator%(T val) {
 mLua->Push(val);
 ++mArguments;
 return *this;
}
A: 

For one, operator>> is a binary operator. That means it has to take two arguments. The first argument has to be whatever is the type of

LuaCall(l, "test") % "test" % 5 % LuaNil % 2.333

Since that operator returns LuaCall&, I suppose that's what the result of that call (and thus left argument) is.

From that mResult I suppose that you attempt to do that operator as a class member. But I don't think you can specialize member templates.

Finally, I don't think you should specialize for reference types. This

template <> LuaCall& operator>><int>(int val);

should do

sbi
Andreas Bonini
oh, also, if I try operator>> with two arguments it gives an error saying it expects only 1
Andreas Bonini
Then the code you've provided is STILL incomplete, because the error message shows us that your operator>> is a member function but in the question it's a free function!
MSalters
+2  A: 

You'v written operator>> as a unary operator, but it's a binary operator. LeftHandSide >> RightHandSide.

The form std::cout <"Hello" << " world"; therefore is (operator<<(operator<<(std::cout, "Hello"), " world); - the first << returns std::cout for use as the left-hand side of the second <<.

The real problem is that in your code, lookup happens as follows:

  1. Candiate functions are determined (only one candidate, the template)
  2. T is deduced.
  3. Determine which specialization (if any) to instantiate.

In step 2, T==int. In step 3, there are no specializations for T==int so the base template is chosen and instantiated. You might want to use an overload instead of a specialization. The overload would be a better match in step 1 so you don't even get to the point of template argument deduction

MSalters
Well, it's what my code does, isn't it?
Andreas Bonini
Just read your edit and changed it to overloading, now it works perfectly, thanks!
Andreas Bonini
+1  A: 

You cannot use constant values ("test" , 5 or 2.333) where references are expected. Change the template and parameter type of your operator>> to (int, float etc.) when you want this behaviour.

Frank Bollack
That wasn't supposed to be >>, it's % that does something else, someone edited my question replacing the %'s with >>'s. the only >> is >> abc
Andreas Bonini