Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Only overload operator if template argument does

Given a template class A with a single template argument T, is it possible to only overload operators in A which are available for type T? For example:

template <typename T>
class A
{
public:
    #if hasOperator(T, +=)
    T& operator +=(const T &rhs)
    {
        mValue += rhs;
        return mValue;
    }
    #endif

private:
    T mValue;
}


int main()
{
    A<int> a;
    a += 8; //+= will forward to the += for the int

    struct Test {  /*no operators defined*/ };
    A<Test> b; //+= is not implemented since Test does not implement +=
}

I'm writting a generic wrapper class that needs to behave exactly like the template type. So if T has operator +=, A will (at compile time) overload += accordingly. Yes, I could go ahead and just implement every operator in A, but then the compiler will error when T doesn't have a certain operator. At first I though template specialization might be the answer, but that would require a specialization for every type. While this could work and be a lot of typing, it wont because A needs to work with any type (not just what is specialized).

like image 773
Dan Watkins Avatar asked Apr 24 '15 19:04

Dan Watkins


1 Answers

Use expression SFINAE to drop your operator+ from the overload resolution set unless T defines operator+

template <typename T>
class A
{
private:
    T mValue;
public:
    template<typename U=T>
    auto operator +=(const U &rhs)
        -> decltype(mValue += rhs)
    {
        mValue += rhs;
        return mValue;
    }
};

Live demo

like image 106
Praetorian Avatar answered Oct 04 '22 01:10

Praetorian