Why doesn't my templated function promote 'int' to 'T', where 'T' = 'double'?

前端 未结 3 1252
无人及你
无人及你 2021-02-05 07:21

I have a class templated with typename T. It contains a function,

template 
myClass operator+(myClass

        
相关标签:
3条回答
  • 2021-02-05 07:32

    The compiler on overload resolution fails to find a right candidate for operator+ because T is already being deducted to double and literal 5 is an integer. Solution:

    template <typename T1, typename T2, size_t a>
    myClass<T1,a> operator+(myClass<T1,a> lhs, const T2& rhs) {
        return lhs += T1(rhs);
    }
    
    0 讨论(0)
  • 2021-02-05 07:47

    When you are using template argument deduction, all deductions for one template parameter must have the same result.

    In your case, the two deductions for T produce double and int, which are not the same, and so deduction fails.

    What you can do is only use one function argument for template argument deduction, and make the other one undeduced:

    template <typename T, std::size_t A>
    void foo(myClass<T, A> arg1, typename std::common_type<T>::type arg2);
    //                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    

    Note that std::common_type<T>::type is essentially just T, but because the type of arg2 is now a dependent type (its name appears to the right of a ::), it is not deduced. Therefore, only the first argument takes part in deduction and produces T = double unambiguously, and then the second function parameter just has type double, and the usual conversions take place.

    As a rule of thumb, template argument deduction does not cross ::.

    0 讨论(0)
  • 2021-02-05 07:52

    You are running into problems with template type deduction.

    Both arguments are given "equal standing" when deducing the value of T, and in this case the two arguments disagree -- one says T should be int, the other says T should be double.

    The right way to fix this is with Koenig operators.

    Make += and + and the like friends of your class and implement inline:

    template<class T, size_t a>
    class myClass {
      // etc
    public:
      friend myClass operator+(myClass lhs, const T& rhs) {
        lhs += rhs;
        return std::move(lhs);
      }
      friend myClass& operator+=(myClass& lhs, const T& rhs) {
        // do addition, depends on `a`
        return *this;
      }
    };
    

    this technique does something strange. It creates non-template operators based on the template type of the class. These are then found via ADL (Koenig lookup) when you invoke + or +=.

    You get one of these operators per template instantiation, but they aren't template operators, so const T& isn't deduced, and conversion happens as expected.

    0 讨论(0)
提交回复
热议问题