简体   繁体   English

如何使模板化运算符推导出正确的返回类型?

[英]How can I make templated operator deduce correct return type?

Say I want two orthogonal types A and B so that I can write 说我想要两个正交类型A和B,这样我就可以写

A a = b1 * b2; // b1,b2 of type B
B b = a1 * a2; // a1,a2 of type A

The data they share is the same, so I attempted some policy-based design. 它们共享的数据是相同的,因此我尝试了一些基于策略的设计。 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;
}

This fails with: 失败的原因是:

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'

What I understand is that it fails because its only the function arguments that are used by the compiler to generate the instanciation, not the return type. 我了解的是它失败了,因为它仅是编译器用于生成实例的函数参数,而不是返回类型。 Thus the compiler cannot generate the correct instanciation for the operator. 因此,编译器无法为操作员生成正确的实例。

My question (pretty simple): how can I implement this operator ? 我的问题(非常简单):如何实现此运算符?

There is no template specialization required here, the behavior is the same with the two types (but other functions - not shown here - will have a specific implementation for each of the types). 此处不需要模板专门化,这两种类型的行为相同(但是其他功能(此处未显示)将为每种类型具有特定的实现)。 But I want to enforce the fact that that you cannot do: A a = a1 * a2; 但是我要强制执行一个事实,即您无法执行以下操作: A a = a1 * a2;

Side note: couldn't find any question with this topic, if you find one, please link! 旁注:找不到与此主题相关的任何问题,如果您发现任何问题,请链接!

You can implement it as two (non-template) free functions. 您可以将其实现为两个(非模板)免费功能。 If the implementation is exactly the same, these can specify the return type for a shared implementation. 如果实现完全相同,则它们可以指定共享实现的返回类型。

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); }

You can create a trait that maps isA to isB , and isB to isA . 您可以创建一个映射特质isAisBisBisA

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 );
};

Unfortunately C++ doesn't use return type to deduce template parameters (some other languages can do it), so you can do nothing with the template. 不幸的是,C ++不使用返回类型来推断模板参数(某些其他语言可以做到),因此您无法对模板做任何事情。

However to make 但是要

A a = b1 * b2; // b1,b2 of type B

working you may implement implicit conversion constructor so that first you'll get type B as a result of multiplication operator and then it will be cast to A type: 工作时,您可以实现隐式转换构造函数,以便首先通过乘法运算符获得B型,然后将其转换为A型:

template <typename U>
myClass(const myClass<U>& other)  {} // copy conversion constructor
template <typename U>
myClass(myClass<U>&& other)  {} // move conversion constructor

so that 以便

A a = b1 * b2;

will be equivalent to 相当于

A a = A(b1 * b2);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM