Template operator overload definitions

I have some function objects, each of which defines different two-parameter operator overloads ():

class Foo {};
class Bar {};

struct Functor1 {
    double operator()(const Foo &, const Bar &)  { return 2.2; }
    double operator()(const Bar &, const Foo &)  { return 3.1; }
};

struct Functor2 {
    int operator()(const Foo &, const Foo &)  { return 2; }
    int operator()(const Bar &, const Bar &)  { return 3; }
};

Now what I want to do is write a utility that allows you to bind these functors one by one to the binary operator. Here is my attempt:

#define ATTACH_FUNCTOR_TO_OPERATOR(OPERATOR, FUNCTOR) \
    template<typename Operand1, typename Operand2> \
    decltype(FUNCTOR(std::declval<Operand1>(), std::declval<Operand2>())) \
    operator OPERATOR(const Operand1 &operand1, const Operand2 &operand2) { \
        return FUNCTOR(operand1, operand2); \
    }

This works fine the first time:

ATTACH_FUNCTOR_TO_OPERATOR(+, Functor1());

but when I add a second call with the same statement:

ATTACH_FUNCTOR_TO_OPERATOR(+, Functor2());

then Visual Studio 2013 tells me that "the function template is already defined."

Note that for any pair of operands there is only one instance +, the return type decltype(FUNCTOR(std::declval<Operand1>(), std::declval<Operand2>()))can be allowed for any particular type. I expected that any other attempts to create instances would fail and not cause any problems - aka SFINAE.

enable_if .

++ 11?

, VS2013?

+3
2

V++. :

template<typename T> void f(decltype(T::a)) {}
template<typename T> void f(decltype(T::b)) {}

source_file.cpp(2): C2995: 'void f ( )': function         source_file.cpp(1): . 'f'

, V++ " " (.. decltype) , .

:

#define ATTACH_FUNCTOR_TO_OPERATOR(OPERATOR, FUNCTOR) \
    template<typename Operand1, typename Operand2> \
    typename std::conditional<true, \
        decltype(FUNCTOR(std::declval<Operand1>(), std::declval<Operand2>())), \
        std::integral_constant<int, __LINE__>>::type \
    operator OPERATOR(const Operand1 & operand1, const Operand2 &operand2) { \
        return FUNCTOR(operand1, operand2); \
    }
+4

ideone , , - VS2013. ++, , .

#include <iostream>
#include <type_traits>
using namespace std;

class Foo {};
class Bar {};

struct Functor1
{
    static double functor(const Foo &) { return 2.2; }
};

struct Functor2
{
    static int functor(const Bar &) { return 3; }
};

template<typename Operand>
auto test(const Operand &operand) -> decltype(Functor1::functor(operand))
{
    return Functor1::functor(operand);
}

template<typename Operand>
auto test(const Operand &operand) -> decltype(Functor2::functor(operand))
{
    return Functor2::functor(operand);
}

int main()
{
    cout << test(Foo()) << endl << test(Bar());
    return 0;
}

VS2013, : " ". , . , .

, , enable_if, , .

: http://ideone.com/JbDKDF

:

VS2012 SP1 (+ ) ( C:: a (T & &...))

+2

All Articles