Negative tive C ++ clause 46: When type conversion is required, define non-member functions for the template.

Source: Internet
Author: User

Clause 24 explains why only non-member functions can "implement implicit type conversion on all real parameters ". These terms templated rational and operator:

Template <typename T>
Class rational {
Rational (const T & number = 0,
Const T & Denominator = 1 );
Const T number () const;
Const t denominator () const;
};
Template <typename T>
Const rational <t> operator * (const rational <t> & LHS, const rational <t> & RHs)
{......}

Like Clause 24, we hope to support mixed arithmetic operations. We hope that the code can be compiled smoothly:

Rational <int> onehalf (1, 2 );
Rational <int> result = onehalf * 2; // error! Compilation fails.

Within Clause 24, the compiler knows what function we are trying to call (that is, the operator * that accepts two rationals parameters), but here the compiler does not know which function we want to call. Instead, they tried to figure out which functions were made available (generated) by the template named operator. They know that a function named "operator * and accepting two rational <t> Parameters" should be available, but to do this, you must first determine what t is. The problem is that they are not capable of this.

To derive T, they look at the parameter types in the operator * Call action. Each parameter is considered separately.

Derivation with onehalf is not difficult. T must be Int. The second parameter is declared as rational <t>, but the second real parameter (2) passed to operator * is int. How does the compiler calculate T based on this? You may expect the compiler to convert 2 to rational <int> using the non-explicit constructor of rational <int>, and then deduce t to int. But they do not, because implicit type conversion functions are never considered during the real parameter derivation of the template. No! This type of conversion is used in the function call process, but you must know that the function exists before you can call a function. To know the parameter type, you must first export the parameter type for the relevant function template (and then the appropriate function can be made available ). Implicit type conversion that occurs through constructor is not considered during the real parameter derivation of template.

There is a way to alleviate the compiler's challenge in deriving the real parameters of the template: The friend declarative in the template class can refer to a specific function.

The class template does not depend on the real parameter derivation of the template (the latter only applies to the function template). Therefore, the compiler can always know t when the class rational <t> is active, therefore, rational <t> class declares an appropriate operator * as its friend function, which simplifies the entire problem:

Template <typename T>
Class rational {
Public:
Friend
Const rational operator * (const rational & LHS, const rational & RHs); // declare the operator * Function
};
Template <typename T>
Const rational <t> operator * (const rational <t> & LHS, const rational <t> & RHs)
{......}

Now the mixed call to operator * can be compiled. Because when the object onehalf is declared as a rational <int>, class rational <int> is implemented as a part of the process, the operds function operator * (which accepts the rational <int> parameter) is automatically declared. The latter is a function rather than a function template, so the compiler can use implicit conversion functions (such as rational non-explicit constructor) when calling it ).

In a class template, the template name can be used as a simple expression of "template and its parameters". Therefore, in rational <t>, we can only write rational without having to write ratioan <t>. Like the following statement:

Template <typename T>
Class rational {
Public:
Friend
Const rational <t> operator * (const rational <t> & LHS, const rational <t> & RHs); // declare the operator * Function
};

However, simple expressions (stenography) are easy and common.

This function is only declared in rational and is not defined. We intend to make the operator * template outside the class provide the definition, but it does not work. When we declare a function in the class rational template, we have the responsibility to define that function.

Perhaps the simplest and most feasible method is to merge the operator * function ontology into its declaration:

Template <typename T>
Class rational {
Public:
Friend
Const rational operator * (const rational & LHS, const rational & RHs); // declare the operator * Function
{
Return rational (LHS. numerator () * RHS. numerator (),
LHS. denominator () * RHS. denominator ());
}
};

Although we use friend, it has nothing to do with the traditional use of "accessing the Non-Public component of the class" of friend. To make the type conversion happen to all parameters, we need a non-member function: to make this function automatically available, we need to declare it within a class: the only way to declare the non-member function within the class is to make it a friend.

All functions defined in the class are implicitly inline, including friend functions such as operator. You can minimize the impact of such an inline statement by making operator * do nothing and only call a helper function defined outside the class. Rational is a template, which means that this helper function is usually a template. The rational header file code looks like this:

Template <typename T> class rational; // declare a rational Template
Template <typename T>
Const rational <t> domultiply (const rational <t> & LHS, const rational <t> & RHs); // declare helper Template

Template <typename T>
Class rational {
Public:
...
Friend
Const rational <t> operator * (const rational <t> & LHS, const rational <t> & RHs );
{
Return domultiply (LHS, RHS); // make friend call helper
}
};

Many compilers force you to put all template definitions into the header file, so you may need to define domultiply in the header file (article 30, such templates do not need to be inline ), it looks like this:

Template <typename T>
Const rational <t> domultiply (const rational <t> & LHS, const rational <t> & RHs)
{
Return rational <t> (LHS. numerator () * RHS. numerator (),
LHS. denominator () * RHS. denominator ());
}

As a template, domultiply certainly does not support mixed multiplication, but it does not. It is called only by operator *, while operator * supports hybrid operations!

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.