Is there a way to specify a precedence among user defined conversions? - c++

Disclaimer: I know that using user defined implicit conversions is often discouraged. However, in our project, we need these conversions for various template classes to work well with each other.
I need to define a precedence of user defined conversions, e.g.:
struct X{}
struct Y{}
struct Z{
operator X(){...}
operator Y(){...}
}
void foo(X x){...}
void foo(Y y){...}
// somewhere in some template client code
...{
Z z = ...;
...
foo(z); // WILL NOT COMPILE
}
This will not compile, as the conversion from Z to either X or Y is ambiguous. Is there a way to resolve this ambiguity. I.e, can I somehow tell the compiler: if there is a function overloaded for X and Y, then prefer to cast Z to X instead of failing to compile.
I know that there is no simple way to specify this. But maybe some template magic and a wrapping template struct that I am not aware of might do the trick. I am allowed to change the client code. I cannot use an explicit cast, as the client code is a templated code that is not aware about the type Z and the available overloads of foo.

You can do something like "prioritized call", with a pattern like this:
struct P2 {};
struct P1: P2 {};
template<class A>
void foo(A x, P1, typename std::common_type<X,A>::type* =nullptr)
{ foo(static_cast<X>(x)); }
template<class A>
void foo(A y, P2, typename std::common_type<Y,A>::type* =nullptr)
{ foo(static_cast<Y>(y)); }
template<class A> void foo(A a) { foo(a,P1()); }
being P2 a base for P1 and the call made with P1, if common_type can compile, the first version goes. If it cannot compile, the first version is like not existent (SFINAE) and the second goes. If it cannot compile as well ... if A is just X or just Y the respective original foo is called, otherwise this cannot compile being types incompatible.
Note that you can even generalize the "priority" as
template<size_t N> struct P: P<N+1> {}
template<> struct P<10> {}
declare SFINAE functions taking P<1>, P<2> etc. up to P<10>, and place the root call with P<0>()

Here is a little system that smart casts a variable to to a sequence of types Ts... such that the first element in the list Ts... that the variable implicitly converts to is the one chosen:
namespace details {
template<class...>struct types{using type=types;};
template<class U, class Types, class=void>
struct smart_cast_t:std::false_type {
using type=U;
template<class A>
U operator()(A&& a)const{return std::forward<A>(a);}
};
template<class U, class T0, class...Ts>
struct smart_cast_t<
U, types<T0, Ts...>,
typename std::enable_if<std::is_convertible<U, T0>::value>::type
>:std::true_type
{
using type=T0;
template<class A>
T0 operator()(A&& a)const{return std::forward<A>(a);}
};
template<class U, class T0, class...Ts>
struct smart_cast_t<
U, types<T0, Ts...>,
typename std::enable_if<!std::is_convertible<U, T0>::value>::type
>:smart_cast_t< U, types<Ts...> >
{};
}
template<class... Ts, class U>
auto smart_cast( U&& u )
-> decltype(details::smart_cast_t< U, details::types<Ts...> >{}( std::forward<U>(u) ))
{
return details::smart_cast_t< U, details::types<Ts...> >{}( std::forward<U>(u) );
}
Now, the idea is that we can now modify foo as follows:
void foo_impl(X);
void foo_impl(Y);
template<class A>
void foo(A&& a) {
foo_impl( smart_cast<X, Y>(std::forward<A>(a)) );
}
and foo casts the A to X if possible, and if not to Y.
We could write up an entire system whereby we pass in a description of the overloads of foo in a package like types< types<X,Y> > and an overload set of foo to some magic code, which spits out a dispatcher, but that would be over engineering.
live example
This uses C++11 features. With C++14 we get to drop some verbage in smart_cast.
The design is pretty simple. We create a types bundle to work with bundles of types (just boilerplate).
Then our details::smart_cast_t has a fallback base specialization that just converts our U to U. If we can convert U to the first type, we do so. Otherwise, we recurse on our parent type, possibly terminating in the base specialization.
I hide that in details, so our public function is simple -- it is smart_cast< type1, type2, type3, etc >( expression ). We don't have to pass U the type of the expression, as we deduce it, then pass it into details for the work to be done.
At run time this reduces to a single implicit cast: all the above is what is done at compile time.
About the only downside is that this can result in warnings on some compilers, as we use implicit conversion. Add a static_cast<T0> to the first non-base specialization of smart_cast_t to avoid this.
I inherited smart_cast_t from true_type and false_type needlessly. This means that the value of smart_cast_t<U, types<Ts...>>::value will tell you if U converted to any of Ts..., or was just left alone as a U.
The caller is responsible for rvalue vs lvalue categories. If the cast fails, it will return a U not a U&& if passed an rvalue. The fallback -- to U -- I think will generate better error messages, but if you prefer that smart_cast<int, double>(std::string("hello")) fail to compile instead of returning a std::string, simply remove the operator() from the base specialization of smart_cast_t.
Speaking of which, I also don't work right for smart_cast<int, double>(""). Might need some typename std::decay<U>::types or something in there.

Yes, cast it explicitly:
foo(static_cast<Y>(z));

Related

Self referential c++20 concepts

What is the moral equivalent to the following invalid code?
// Suppose you want to check, as part of a concept,
// if some operation on a type results in a type that models such concept.
// you cannot constrain the resulting type with the same concept
// in the same way you can't have self referential types
// (that would result in recursive definitions)
template<class T>
concept Int = requires(const T& a, const T& b) {
{ a + b } -> Int; // compiler don't know what to do
};
Suppose you want to check, as part of a concept, if some operation on a type results in a type that models such concept.
That's infinite recursion. Like any functional recursion, you have to have a terminal condition. The normal way to define a terminal condition for template arguments is via a specialization. But concepts explicitly cannot be specialized, so there can be no terminal condition.
It's also logically incoherent, since you're trying to write a definition by using the thing you're trying to define. There is no "moral equivalent" to something that by definition doesn't make sense.
Your concept appears to be saying "T shall be a thing that I can add to another T and yield..." what? Do you want it to be able to yield some unrelated type U which can be added to another U to yield... again, what? Even ignoring that question, should U be able to be added to T? And if so, what should that yield?
When writing a concept, start with the use case, start by deciding what operations you want to perform.
It is possible to do such recursive template check, but it makes code difficult to read.
The principle is to forward recursive template check to a function found by dependent name look up, whose constraints will only be verified if the type does not already belong to a list of already checked types... If the type belong to the list of already checked type, the function is disabled by SFINAE, and an other function that does not recursively refers to the concept is selected by overload resolution:
See it in action: compiler-explorer-link
#include <type_traits>
namespace trying{
struct to_do{};
template <class...Checked, class T>
std::enable_if_t <(std::is_same_v <T,Checked> || ...), std::true_type>
too_complex(T &&, to_do);
template <class...Checked, class T>
std::false_type
too_complex(T &&,...);
}
template <class U, class T, class...Checked>
concept Integer_= requires(const T& a, const T& b, const U& to_be_readable)
{
requires decltype(too_complex <T, Checked...> (a + b, to_be_readable))::value ;
};
template <class T, class...Checked>
concept Integer = Integer_ <trying::to_do, T, Checked...>;
namespace trying{
template <class...Checked, class T>
requires (Integer <T, Checked...>)
std::enable_if_t <!(std::is_same_v <T,Checked> || ...), std::true_type>
too_complex(T &&, to_do);
}
struct x{
auto
operator + (x) const -> int;
};
struct y{
auto
operator + (y) const -> void*;
};
struct z2;
struct z1{
auto
operator + (z1) const -> z2;
};
struct z2{
auto
operator + (z2) const -> z1;
};
static_assert (Integer <int>);
static_assert (Integer <x>);
static_assert (!Integer <y>);
static_assert (Integer <z1>);
static_assert (Integer <z2>);
So yes it is possible... but I don't think it should be done.

Technique to cause compile time error if members are added to class in C++

Let's say you have some POD which contain multiple public members. You also have some classes which serialize and deserialize these objects from various sources. Are there any coding techniques, other than unit tests, which would make sure that when you add a member to the class, you update any additional code that needs to know about the added field.
i.e. I'd love a technique that would cause compile time errors until all code was updated to handle the new fields.
There's no reflection in C++.
But a solution, which also has the attractive property that it doesn't pollute your compiled code, is to use a static_assert(sizeof(YourType) == x, <message>) where x is a hard-coded constant, contingent on your compiler.
Any member added to YourType will change sizeof, and induce a compile time failure.
(There might be some instances where this doesn't work if a new member occupies the space that was previously end-of-structure padding. Try the approach first with your compiler to see if this is feasible.)
from c++17 on, you could exploit structured bindings: you add a convention to your codebase that whenever a function requires the POD to be the up-to-date version, that function should access the pod via structured bindings:
struct A { int a,b,c; };
void foo( A& the_pod )
{
auto& [a,b,c] = the_pod;
// ... use a,b,c
}
adding a member to A would make the code not compile anymore...
note that relying on A's sizeof as already suggested could break the code when changing compiler ( this is bad assuming your functions depending on A ( like your serialization code ) happens to be portable )
moreover, the error would tell you that something is wrong, whereas this solution would also tell you where is wrong ...
the only downside I see being that it relies on a programmer convention ( but, assuming A to be a growing only POD is also a convention anyway ... )
In c++11, you can do full reflection of default-aligned AggregateTypes if they're DefaultConstructible (note[1]); construct-only reflection id non-DC. This will be tricky, but the sketch is not that hard (credits: magic_get).
Observe that these types have a ctor that has all the types of the class and there's no other ctor taking more params. Hence, you can write:
template<typename T, typename... Args>
using constructed_from = decltype(T{std::forward<Args>(std::declval<Args>())...});
You can write (thanks, Antony)
template<size_t i>
struct Ubiq {
template<typename T>
operator T() const; /* undef'd */
};
Read the doc and examples of is_detected if you're not familiar with it: it allows you to detect if an expression is valid. Here you'll test if T is constructible from N Ubiq instances, i.e., if it has at least N params.
At this point, you're ready: you just need to check if it's constructible from your expected types, but not from your types and an Ubiq.
If you want full reflection, you add a constexpr size_t ctor_param_cnt(), then you implement a visit_ctor() that takes a template<typename T, size_t i> struct Generator; which will generate each field via operator FieldType() const(which is usually a template). For read access, you need to store field offsets [1].
[1] Note that this requires an ABI where layout of a struct depends only on types in it. Itanium ABI satisfies it.
Example (for your use case):
#include <string>
#include <type_traits>
struct S1 {
int i;
std::string j;
};
struct S2 {
int i;
std::string j;
int k;
};
template<typename T, typename... Args>
using constructed_from =
typename std::decay<decltype(
T{ std::forward<Args>(std::declval<Args>())... }
)>::type;
template<size_t i>
struct Ubiq {
template<typename T>
operator T() const; /* undef'd */
};
template<typename... Ts> struct make_void { typedef void type;};
template<typename... Ts> using void_t = typename make_void<Ts...>::type;
template<typename T, typename AlwaysVoid, typename... Args>
struct is_constructible_from : std::false_type {};
template<typename T, typename... Args>
struct is_constructible_from<T, void_t<constructed_from<T, Args...>>, Args...> : std::true_type {};
static_assert( is_constructible_from<S1, void, int, std::string>::value, "");
static_assert(!is_constructible_from<S1, void, int, std::string, Ubiq<0>>::value, ""); // note: !
static_assert( is_constructible_from<S2, void, int, std::string>::value, "");
static_assert( is_constructible_from<S2, void, int, std::string, Ubiq<0>>::value, ""); // note: no !

Can we use the detection idiom to check if a class has a member function with a specific signature?

Given a (reduced) implementation of the detection idiom
namespace type_traits
{
template<typename... Ts>
using void_t = void;
namespace detail
{
template<typename, template<typename...> class, typename...>
struct is_detected : std::false_type {};
template<template<class...> class Operation, typename... Arguments>
struct is_detected<void_t<Operation<Arguments...>>, Operation, Arguments...> : std::true_type {};
}
template<template<class...> class Operation, typename... Arguments>
using is_detected = detail::is_detected<void_t<>, Operation, Arguments...>;
template<template<class...> class Operation, typename... Arguments>
constexpr bool is_detected_v = detail::is_detected<void_t<>, Operation, Arguments...>::value;
}
we can easily check if a class foo contains a member function bar
struct foo {
int const& bar(int&&) { return 0; }
};
template<class T>
using bar_t = decltype(std::declval<T>().bar(0));
int main()
{
static_assert(type_traits::is_detected_v<bar_t, foo>, "not detected");
return 0;
}
However, as you can see, we cannot detect that foo::bar's argument type is int&&. The detection succeeds, cause 0 can be passed to foo::bar. I know that there are plenty of options to check for the exact signature of a (member) function. But I would like to know, if it's possible to modify this detection toolkit in order to detect that foo::bar's argument type is exactly int&&.
[I've created a live demo of this example.]
Without changing your type_traits, you may do
template<typename T, T> struct helper {};
template<class T>
using bar_t = decltype(helper<const int& (T::*)(int&&), &T::bar>{});
Demo
Adapting the ideas of dyp and Jarod42, I've came up with
template<class T, typename... Arguments>
using bar_t = std::conditional_t<
true,
decltype(std::declval<T>().bar(std::declval<Arguments>()...)),
std::integral_constant<
decltype(std::declval<T>().bar(std::declval<Arguments>()...)) (T::*)(Arguments...),
&T::bar
>
>;
Notice that bar_t will be the return type of a bar call. In this way, we stay consistent with the toolkit. We can detect the existence by
static_assert(type_traits::is_detected_v<bar_t, foo, int&&>, "not detected");
However, while this solution does exactly what I intended, I hate that I need to write "so much complicated code" for every method I want to detect. I've asked a new question targeting this issue.
I don't think this works for checking const qualifiers.
decltype(std::declval<T>().bar(std::declval<Arguments>()...)) (T::*)(Arguments...)
always produces a non-const function pointer type, whereas &T::bar will produce a const function pointer if bar is marked const.
This will then fail trying to convert the const pointer type to the non-const pointer type for storage in integral_constant.

Match type of inherited member functions

I have the following snipped of code, which does not compile.
#include <iostream>
struct A {
void foo() {}
};
struct B : public A {
using A::foo;
};
template<typename U, U> struct helper{};
int main() {
helper<void (A::*)(), &A::foo> compiles;
helper<void (B::*)(), &B::foo> does_not_compile;
return 0;
}
It does not compile since &B::foo resolves to &A::foo, and thus it cannot match the proposed type void (B::*)(). Since this is part of a SFINAE template that I am using to check for a very specific interface (I'm forcing specific argument types and output types), I would like for this to work independently of inheritances, while keeping the check readable.
What I tried includes:
Casting the second part of the argument:
helper<void (B::*)(), (void (B::*)())&B::foo> does_not_compile;
This unfortunately does not help as the second part is now not recognized as a constant expression, and fails.
I've tried assigning the reference to a variable, in order to check that.
constexpr void (B::* p)() = &B::foo;
helper<void (B::* const)(), p> half_compiles;
This code is accepted by clang 3.4, but g++ 4.8.1 rejects it, and I have no idea on who's right.
Any ideas?
EDIT: Since many comments are asking for a more specific version of the problem, I'll write it here:
What I'm looking for is a way to explicitly check that a class respects a specific interface. This check will be used to verify input arguments in templated functions, so that they respect the contract that those functions require, so that compilation stops beforehand in case the class and a function are not compatible (i.e. type traits kind of checking).
Thus, I need to be able to verify return type, argument type and number, constness and so on of each member function that I request. The initial question was the checking part of the bigger template that I'm using to verify matches.
A working solution to your problem as posted at https://ideone.com/mxIVw3 is given below - see also live example.
This problem is in a sense a follow-up of Deduce parent class of inherited method in C++. In my answer, I defined a type trait member_class that extracts a class from a given pointer to member function type. Below we use some more traits to analyse and then synthesize back such a type.
First, member_type extracts the signature, e.g. void (C::*)() gives void():
template <typename M> struct member_type_t { };
template <typename M> using member_type = typename member_type_t <M>::type;
template <typename T, typename C>
struct member_type_t <T C::*> { using type = T;};
Then, member_class extracts the class, e.g. void (C::*)() gives C:
template<typename>
struct member_class_t;
template<typename M>
using member_class = typename member_class_t <M>::type;
template<typename R, typename C, typename... A>
struct member_class_t <R(C::*)(A...)> { using type = C; };
template<typename R, typename C, typename... A>
struct member_class_t <R(C::*)(A...) const> { using type = C const; };
// ...other qualifier specializations
Finally, member_ptr synthesizes a pointer to member function type given a class and a signature, e.g. C + void() give void (C::*)():
template <typename C, typename S>
struct member_ptr_t;
template <typename C, typename S>
using member_ptr = typename member_ptr_t <C, S>::type;
template <typename C, typename R, typename ...A>
struct member_ptr_t <C, R(A...)> { using type = R (C::*)(A...); };
template <typename C, typename R, typename ...A>
struct member_ptr_t <C const, R(A...)> { using type = R (C::*)(A...) const; };
// ...other qualifier specializations
The two previous traits need more specialization for different qualifiers to be more generic, e.g. const/volatile or ref-qualifiers. There are 12 combinations (or 13 including data members); a complete implementation is here.
The idea is that any qualifiers are transferred by member_class from the pointer-to-member-function type to the class itself. Then member_ptr transfers qualifiers from the class back to the pointer type. While qualifiers are on the class type, one is free to manipulate with standard traits, e.g. add or remove const, lvalue/rvalue references, etc.
Now, here is your is_foo test:
template <typename T>
struct is_foo {
private:
template<
typename Z,
typename M = decltype(&Z::foo),
typename C = typename std::decay<member_class<M>>::type,
typename S = member_type<M>
>
using pattern = member_ptr<C const, void()>;
template<typename U, U> struct helper{};
template <typename Z> static auto test(Z z) -> decltype(
helper<pattern<Z>, &Z::foo>(),
// All other requirements follow..
std::true_type()
);
template <typename> static auto test(...) -> std::false_type;
public:
enum { value = std::is_same<decltype(test<T>(std::declval<T>())),std::true_type>::value };
};
Given type Z, alias template pattern gets the correct type M of the member pointer with decltype(&Z::foo), extracts its decay'ed class C and signature S, and synthesizes a new pointer-to-member-function type with class C const and signature void(), i.e. void (C::*)() const. This is exactly what you needed: it's the same with your original hard-coded pattern, with the type Z replaced by the correct class C (possibly a base class), as found by decltype.
Graphically:
M = void (Z::*)() const -> Z + void()
-> Z const + void()
-> void (Z::*)() const == M
-> SUCCESS
M = int (Z::*)() const& -> Z const& + int()
-> Z const + void()
-> void (Z::*)() const != M
-> FAILURE
In fact, signature S wasn't needed here, so neither was member_type. But I used it in the process, so I am including it here for completeness. It may be useful in more general cases.
Of course, all this won't work for multiple overloads, because decltype doesn't work in this case.
If you simply want to check the existence of the interface on a given type T, then there're better ways to do it. Here is one example:
template<typename T>
struct has_foo
{
template<typename U>
constexpr static auto sfinae(U *obj) -> decltype(obj->foo(), bool()) { return true; }
constexpr static auto sfinae(...) -> bool { return false; }
constexpr static bool value = sfinae(static_cast<T*>(0));
};
Test code:
struct A {
void foo() {}
};
struct B : public A {
using A::foo;
};
struct C{};
int main()
{
std::cout << has_foo<A>::value << std::endl;
std::cout << has_foo<B>::value << std::endl;
std::cout << has_foo<C>::value << std::endl;
std::cout << has_foo<int>::value << std::endl;
return 0;
}
Output (demo):
1
1
0
0
Hope that helps.
Here's a simple class that passes your tests (and doesn't require a dozen of specializations :) ). It also works when foo is overloaded. The signature that you wish to check can also be a template parameter (that's a good thing, right?).
#include <type_traits>
template <typename T>
struct is_foo {
template<typename U>
static auto check(int) ->
decltype( static_cast< void (U::*)() const >(&U::foo), std::true_type() );
// ^^^^^^^^^^^^^^^^^^^
// the desired signature goes here
template<typename>
static std::false_type check(...);
static constexpr bool value = decltype(check<T>(0))::value;
};
Live example here.
EDIT :
We have two overloads of check. Both can take a integer literal as a parameter and because the second one has an ellipsis in parameter list it'll never be the best viable in overload resolution when both overloads are viable (elipsis-conversion-sequence is worse than any other conversion sequence). This lets us unambiguously initialize the value member of the trait class later.
The second overload is only selected when the first one is discarded from overload set. That happens when template argument substitution fails and is not an error (SFINAE).
It's the funky expression on the left side of comma operator inside decltype that makes it happen. It can be ill-formed when
the sub-expression &U::foo is ill-formed, which can happen when
U is not a class type, or
U::foo is inaccesible, or
there is no U::foo
the resulting member pointer cannot be static_cast to the target type
Note that looking up &U::foo doesn't fail when U::foo itself would be ambiguous. This is guaranteed in certain context listed in C++ standard under 13.4 (Address of overloaded function, [over.over]). One such context is explicit type conversion (static_cast in this case).
The expression also makes use of the fact that T B::* is convertible to T D::* where D is a class derived from B (but not the other way around). This way there's no need for deducing the class type like in iavr's answer.
value member is then initialized with value of either true_type or false_type.
There's a potential problem with this solution, though. Consider:
struct X {
void foo() const;
};
struct Y : X {
int foo(); // hides X::foo
};
Now is_foo<Y>::value will give false, because name lookup for foo will stop when it encounters Y::foo. If that's not your desired behaviour, consider passing the class in which you wish to perform lookup as a template parameter of is_foo and use it in place of &U::foo.
Hope that helps.
I suggest using decltype to generically determine the type of the member function pointers:
helper<decltype(&A::foo), &A::foo> compiles;
helper<decltype(&B::foo), &B::foo> also_compiles;
It may seem like a DRY violation, but repeating the name is fundamentally no worse than specifying the type separately from the name.

How can I pass an arithmetic operator to a template?

I want to somehow merge templates like these into one:
template <class Result, class T1, class T2>
class StupidAdd
{
public:
T1 _a; T2 _b;
StupidAdd(T1 a, T2 b):_a(a),_b(b) {}
Result operator()() { return _a+_b; }
};
template <class Result, class T1, class T2>
class StupidSub
{
public:
T1 _a; T2 _b;
StupidSub(T1 a, T2 b):_a(a),_b(b) {}
Result operator()() { return _a-_b; }
};
(followed by the same code for Mul, Div, etc) where all the code is the same,
except for the actual "+", "-" (and "StupidAdd", "StupidSub", etc).
These Stupid "functors" are then used by another template.
How can I avoid the repetition, WITHOUT the preprocessor?
(The reason I got into templates was to avoid the preprocessor)
That is, how can I pass arithmetic operators into a template?
Maybe you could use std::plus<T>, std::minus<T>, std::multiplies<T> and std::divides<T>. However, these will work only if both operands are of the same type, or probably if the left one can be converted to the type of the first one.
I don't see any way to achieve what you're trying to do, except by using the preprocessor. Any good reasons for not wanting macros ?
If you want to make sure the return type is large enough to contains the result, you could do something along this way:
#include <functional>
#include <boost/mpl/if_.hpp>
// Metafunction returning the largest type between T and U
// Might already exist in Boost but I can't find it right now...maybe
// boost::math::tools::promote_args
template <typename T, typename U>
struct largest :
boost::mpl::if_<
boost::mpl::bool_<(sizeof(T) > sizeof(U))>,
T,
U
>
{};
template <typename T, typename U, template <typename S> class Op>
struct Foo
{
typedef typename largest<T, U>::type largeType;
largeType bar(const T & t, const U & u)
{
return Op<largeType>()(t, u); // Applies operator+
}
};
int main()
{
Foo<int, double, std::plus> f;
double d = f.bar(12, 13.0); // takes int and double, returns double
}
Here, I used Boost MPL to write the largest metafunction, but you could write your own if metafunction if you cannot use Boost (class template parameterized by two types and a bool, specialized for true and false).
To determine the return type of an expression, you could also have a look at boost::result_of which, if I understand correctly, is equivalent to the upcoming decltype operator in C++0x.
Thanks Luc, this is very cool.
I finally did it in a simpler way:
#include <functional>
template <
class Result,
class T1,
class T2,
template <class ReturnType> class BinaryOp>
class Stupido
{
public:
T1 _a; T2 _b;
Stupido(T1 a, T2 b):_a(a),_b(b) {}
Result operator()() { return BinaryOp<Result>()((Result)_a,(Result)_b); }
};
And used the "plus", "minus" when instantiating Stupido.
The cast to "Result" was enough for my needs (int + double => double + double => double)
I think there's an improvement to OldCoder's solution:
#include <functional>
template <class Result,
template <class Result> class BinaryOp>
struct Stupido
{
template <typename T1, typename T2>
Result operator()(const T1& a, const T2& b) { return BinaryOp<Result>()((Result)a,(Result)b); }
};
This way the call can be made as:
Stupido<int, std::plus > stup;
int result = stup(3.0f, 2.0);
and the same function object can be used with multiple operands, so it could be passed in to a std::transform call.
I believe there must be a way to remove one Result from the template declaration, but I am unable to find it.
I'd use the C++ 0x decltype and the new definition of auto. You'll still need to define the classes, but using these, you can do a nicer job of defining them. They'll still be about as much work to define, but at least using them will be considerably cleaner. In particular, you can use decltype/auto to deduce the correct return type instead of having to specify it explicitly.
These are available with a fair number of recent compilers -- Intel C++, g++, Comeau, the beta of VC++ 2010, and even the most recent iteration of Borland/Inprise/Embarcadero/this week's new name.