Chcę wykonać następujące czynności ze specjalizacją według cech.
Array Aa = Scalar in_a
użyłbyoverload I
.Array Aa = Array Bb
użyłbyoverload II
.
W poniższym kodzie overload II
nigdy się nie przyzwyczajaj.
Ktoś o tym wspomniał T1
nie można wydedukować w overload II
.
Jak to naprawić?
Użyłem powłoki C ++ do skompilowania kodu w 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)
}
Odpowiedzi:
2 dla odpowiedzi № 1Oto Twój kod uproszczony i działający zgodnie z przeznaczeniem:
#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)
}
2 dla odpowiedzi nr 2
Twój kod powinien być
template <typename T>
std::enable_if_t<is_int<T>::value, A&>
operator=(const T& input){
val = 2 * input; //Overload I
return *this;
}
template <typename T>
std::enable_if_t<is_A<T>::value, A&>
operator=(T& rhs){
val = 5 * rhs.val; //Overload II
return *this;
}
Ale w twoim przypadku jeszcze prostsze
A& operator=(int input){
val = 2 * input; //Overload I
return *this;
}
A& operator=(const A& rhs){
val = 5 * rhs.val; //Overload II
return *this;
}
1 dla odpowiedzi nr 3
Czy naprawdę potrzebujesz całej magii szablonów do swojej prostej skrzynki?
#include <iostream>
class A;
class A{
public:
int val;
void print(void){
std::cout << val << std::endl;
}
void operator =(const A& in){ val = in.val*5; }
void operator =(int in) { val = in*2; }
};
int main(void){
A Aa;
A Bb;
Aa = 3;
Bb = Aa;
Aa.print(); //This should give 6. (3x2)
Bb.print(); //This should give 30. (6x5)
return 0;
}