说我想要两个正交类型A和B,以便我可以写
A a = b1 * b2; // b1,b2 of type B
B b = a1 * a2; // a1,a2 of type A
它们共享的数据是相同的,因此我尝试了一些基于策略的设计。 Some code:
#include <type_traits>
struct isA {};
struct isB {};
template<typename T>
struct myClass
{
int _data;
template<typename U>
myClass<U> operator * ( const myClass<T>& other );
};
template<typename T>
template<typename U>
myClass<U> myClass<T>::operator * ( const myClass<T>& other )
{
// just an idea, will not be needed if correct instanciation
static_assert( std::is_same<U,T>::value, "cannot return same type" );
// ... here, some code
}
int main()
{
myClass<isA> a1,a2;
myClass<isB> b = a1 * a2;
}
此操作失败,并显示以下信息:
main.cpp: In function 'int main()':
main.cpp:26:25: error: no match for 'operator*' (operand types are
'myClass<isA>' and 'myClass<isA>')
myClass<isB> b = a1 * a2;
main.cpp:12:16: note: candidate: 'template<class U> myClass<U> myClass<T>::operator*(const myClass<T>&) [with U = U; T = isA]'
myClass<U> operator * ( const myClass<T>& other );
main.cpp:12:16: note: template argument deduction/substitution failed:
main.cpp:26:27: note: couldn't deduce template parameter 'U'
我了解的是它失败了,因为它只是编译器用来生成实例化的函数参数,而不是返回类型。因此,编译器无法为运算符生成正确的实例。
我的问题(非常简单):如何实现此运算符?
这里不需要模板专门化,这两种类型的行为是相同的(但是其他功能(此处未显示)将对每种类型都有特定的实现)。但是我想强制执行一个事实,即您无法执行以下操作:A a = a1 * a2;
旁注:找不到与此主题相关的任何问题,如果找到一个问题,请链接!
答案 0 :(得分:3)
您可以将其实现为两个(非模板)自由函数。如果实现完全相同,则可以为共享实现指定返回类型。
namespace detail
{
template<typename Out, typename In>
MyClass<Out> times( const MyClass<In> & lhs, const MyClass<In> & rhs)
{
// shared code here
}
}
myClass<isA> operator * ( const myClass<isB>& lhs, const myClass<isB>& rhs )
{ return detail::times<isA>(lhs, rhs); }
myClass<isB> operator * ( const myClass<isA>& lhs, const myClass<isA>& rhs )
{ return detail::times<isB>(lhs, rhs); }
答案 1 :(得分:2)
您可以创建将isA
映射到isB
,并将isB
映射到isA
的特征。
namespace detail
{
template<typename>
struct myClassTraits;
template<>
struct myClassTraits<isA>
{
using other_type = isB;
};
template<>
struct myClassTraits<isB>
{
using other_type = isA;
};
}
template<typename T>
struct myClass
{
int _data;
using times_t = myClass<typename detail::myClassTraits<T>::other_type>;
times_t operator * ( const myClass& other );
};
答案 2 :(得分:1)
不幸的是,C ++不使用返回类型来推断模板参数(某些其他语言可以做到),因此您不能对模板做任何事情。
但是制作
A a = b1 * b2; // b1,b2 of type B
工作时,您可以实现隐式转换构造函数,这样一来,由于乘法运算符,您将首先得到类型B
,然后将其转换为A
类型:
template <typename U>
myClass(const myClass<U>& other) {} // copy conversion constructor
template <typename U>
myClass(myClass<U>&& other) {} // move conversion constructor
这样
A a = b1 * b2;
将等同于
A a = A(b1 * b2);