如何使模板化运算符推断出正确的返回类型
How can I make templated operator deduce correct return type?
假设我想要两个正交类型 A 和 B,这样我就可以写
A a = b1 * b2; // b1,b2 of type B
B b = a1 * a2; // a1,a2 of type A
它们共享的数据是相同的,因此我尝试了一些基于策略的设计。一些代码:
#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;
旁注:找不到有关此主题的任何问题,如果您找到,请链接!
您可以将其实现为两个(非模板(自由函数。如果实现完全相同,则可以指定共享实现的返回类型。
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); }
您可以创建一个将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 );
};
不幸的是,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);
相关文章:
- 在实例化之前推断函数模板的返回类型
- "auto"推断出 hashtable_policy.h 中的错误类型
- 无法推断返回类型的模板参数
- 推断成员函数的返回类型
- 三元运算符 '?:' 在 4.9.0 之前的 GCC 版本中推断出不正确的类型?
- 为什么"return (str);"推断出与C++中的"return str;"不同的类型?
- 模板化函数以从输入参数推断返回类型 stl-container
- 为什么编译器不能从返回类型中推断出模板参数?
- C++推断要隐式调用的模板函数返回类型
- 从参数的返回类型推断类型
- 将返回类型推断为模板参数类型方法
- 如何允许编译器推断出正确的返回类型以进行模板get函数
- 自动无法推断出正确的返回类型
- 如何使模板化运算符推断出正确的返回类型
- 编译器无法推断出要返回的模板类型
- C++基于输入参数的返回类型推断
- 从函数参数的返回类型推断函数返回类型
- 如何让编译器推断出c++ 11中模板化方法的返回类型
- 类模板化成员函数和返回类型推断
- 返回类型推断:首选哪种方法