rxu rxu - 2 months ago 14
C++ Question

Specialize same operator for different traits

I want to do the following with specialization by traits.


  1. Array Aa = Scalar in_a
    would use
    overload I
    .

  2. Array Aa = Array Bb
    would use
    overload II
    .



In the following code,
overload II
never get used.

Someone mentioned that
T1
cannot be deduced in
overload II
.

How to fix that?

I used the C++ shell to compile the code with C++14.

#include <iostream>
#include <type_traits>

using namespace std;
class A; // forward declaration.

template <typename T>
struct is_A : false_type {};
template <> struct is_A<A> : true_type {};

template <typename T>
struct is_int : false_type {};
template <> struct is_int<int> : true_type {};
template <> struct is_int<long> : true_type {};

class A{
public:
int val;
void print(void){
std::cout << val << std::endl;
}
template <typename T1>
enable_if_t<is_int<T1>::value,void>
operator=(const T1 & input){
val = 2*input; //Overload I
}
template <typename T1>
enable_if_t<is_A<T1>::value,void>
operator=(const T1 & Bb){
val = 5*Bb.val; //Overload II
}
};

int main(void){
A Aa;
A Bb;
int in_a = 3;
Aa = in_a; //This uses overload I as intended.
Bb = Aa; //I want this to use overload II, but
//actually overload I is used.
//This leads to an error during compilation.
Aa.print(); //This should give 6. (3x2)
Bb.print(); //This should give 30. (6x5)
}

Answer

Here is your code simplified and working as intended:

#include <iostream>
#include <type_traits>
#include<utility>

class A;

template <typename T>
struct is_A : std::false_type {};
template <> struct is_A<A> : std::true_type {};

template <typename T>
struct is_int : std::false_type {};
template <> struct is_int<int> : std::true_type {};
template <> struct is_int<long> : std::true_type {};

class A{
public:
    int val;

    void print(void){
        std::cout << val << std::endl;
    }

    template <typename T1>
    std::enable_if_t<is_int<std::decay_t<T1>>::value, void>
    operator=(T1 && input){
        val = 2*std::forward<T1>(input);
    }

    template <typename T1>
    std::enable_if_t<is_A<std::decay_t<T1>>::value,void>
    operator=(T1 && Bb){
        val = 5*std::forward<T1>(Bb).val;
    }
};

int main(void){
    A Aa;
    A Bb;
    int in_a = 3;
    Aa = in_a;
    Bb = Aa;
    Aa.print(); //This should give 6. (3x2)
    Bb.print(); //This should give 30. (6x5)
}