6. Extending return type deduction system

¤³¤Î¥»¥¯¥·¥ç¥ó¤Ç¤Ï¡¢¥æ¡¼¥¶ÄêµÁ¤Î±é»»»Ò¤ò°·¤¦¤¿¤á¤Ë¡¢ ÊÖ¤êÃͤη¿¿äÏÀ¥·¥¹¥Æ¥à¤Î³ÈÄ¥¤¹¤ëÊýË¡¤ò²òÀ⤹¤ë¡£ BLL ¤Ï¥Ç¥Õ¥©¥ë¥È¤Î±é»»»Ò¤ÎÊÖ¤êÃͤη¿¤òÄêµÁ¤·¤Æ¤¤¤ë¤¿¤á¡¢ ¿¤¯¤Î¾ì¹ç¤Ë¤Ï¤³¤ì¤ÏɬÍפʤ¤¡£ Î㤨¤Ð¡¢¤¹¤Ù¤Æ¤ÎÈæ³Ó±é»»»Ò¤Î¥Ç¥Õ¥©¥ë¥È¤ÎÊÖ¤êÃÍ¤Ï bool ¤Ç¤¢¤ê¡¢ ¥æ¡¼¥¶ÄêµÁ¤ÎÈæ³Ó±é»»»Ò¤ÎÊÖ¤êÃͤη¿¤¬ bool ¤Ç¤¢¤ë¸Â¤ê ÊÖ¤êÃͤη¿¿äÏÀ¥¯¥é¥¹¤Î¿·¤·¤¤ÆÃ¼ì²½¤ò½ñ¤¯É¬ÍפϤʤ¤¡£ ¤·¤«¤·¡¢¤³¤ì¤¬ÉÔ²ÄÈò¤Ç¤¢¤ë¾ì¹ç¤â¤¢¤ë¡£

¥ª¡¼¥Ð¡¼¥í¡¼¥É²Äǽ¤Ê¥æ¡¼¥¶ÄêµÁ¤Î±é»»»Ò¤Ï¡¢Ã±¹à¤Þ¤¿¤ÏÆó¹à±é»»»Ò¤Ç¤¢¤ë¡£ ¤½¤Î°ú¿ô¤Î¿ô¤´¤È¤Ë¡¢¤µ¤Þ¤¶¤Þ¤Ê±é»»»Ò¤ÎÊÖ¤êÃͤη¿¤òÄêµÁ¤¹¤ë Æó¤Ä¤ÎÆÃÀ­¥Æ¥ó¥×¥ì¡¼¥È¤¬¤¢¤ë¡£ ¤è¤Ã¤Æ¡¢¤³¤Î¥Æ¥ó¥×¥ì¡¼¥È¤ò»È¤¤ÆÃ¼ì²½¤¹¤ë¤³¤È¤Ë¤è¤ê¡¢ÊÖ¤êÃͤη¿¿äÏÀ¥·¥¹¥Æ¥à¤ò³ÈÄ¥¤¹¤ë¤³¤È¤¬¤Ç¤­¤ë¡£ ñ¹à´Ø¿ô¤Î¤¿¤á¤Î¥Æ¥ó¥×¥ì¡¼¥È¤Ï¡¢ plain_return_type_1<Action, A> ¤È return_type_1<Action, A> ¤Ç¤¢¤ê¡¢Æó¹à´Ø¿ô¤Î¤¿¤á¤Î¤â¤Î¤Ï¡¢ plain_return_type_2<Action, A, B> ¤È return_type_2<Action, A, B> ¤Ç¤¢¤ë¡£

¤³¤ì¤éÁ´¤Æ¤Î¥Æ¥ó¥×¥ì¡¼¥È¤ËÂФ¹¤ëÂè°ì°ú¿ô(Action) ¤Ï¡¢ ±é»»»Ò¤ò»ØÄꤷ¤Æ¤¤¤ë ¥¢¥¯¥·¥ç¥ó¥¯¥é¥¹¤Ç¤¢¤ë¡£ Ʊ¤¸ÊÖ¤êÃͤη¿¤Îµ¬Â§¤ò»ý¤Ã¤¿±é»»»Ò¤Ï¡¢ ¥¢¥¯¥·¥ç¥ó¥°¥ë¡¼¥× ¤Ë¤Þ¤È¤á¤é¤ì¡¢ ¥¢¥¯¥·¥ç¥ó¥¯¥é¥¹¤È¥¢¥¯¥·¥ç¥ó¥°¥ë¡¼¥×¤Î¤ß¤¬±é»»»Ò¤ÎÛ£Ëæ¤µ¤ò²ò·è¤¹¤ë¡£ Îã¤òµó¤²¤ë¤È¡¢operator+¤ò¼¨¤¹¥¢¥¯¥·¥ç¥ó·¿ arithmetic_action<plus_action> ¤¬¤¢¤ë¡£ ¾¤Î¥¢¥¯¥·¥ç¥ó·¿¤Î´°Á´¤Ê¥ê¥¹¥È¤ò Table 2 ¤Ë¼¨¤¹¡£

ñ¹à´Ø¿ô¤Î¾ì¹ç¤Î A ¤äÆó¹à´Ø¿ô¤Î¾ì¹ç¤Î A ¤ä B ¤È¤¤¤Ã¤¿»Ä¤ê¤Î¥Æ¥ó¥×¥ì¡¼¥È°ú¿ô¤Ï¡¢±é»»»Ò¸Æ½Ð¤·¤Î°ú¿ô¤Î·¿¤ò¼¨¤·¤Æ¤¤¤ë¡£ Æó¤Ä¤Î¥Æ¥ó¥×¥ì¡¼¥È·² plain_return_type_n ¤È return_type_n ¤Ï(n ¤Ï£±¤Þ¤¿¤Ï£²)¡¢ °ú¿ô¤Î·¿¤ÎÄ󼨤λÅÊý¤Ë¤ª¤¤¤Æ°Û¤Ê¤ë¡£ Á°¼Ô¤Î¥Æ¥ó¥×¥ì¡¼¥È¤Ç¤Ï¡¢°ú¿ô¤Î·¿¤Ï¾ï¤Ë»²¾È·¿¤Ç¤Ï¤Ê¤¯¡¢ ¤Þ¤¿¡¢const ¤ä volatile ¤È¤¤¤Ã¤¿½¤¾þ»Ò¤â¤Ä¤¤¤Æ¤¤¤Ê¤¤¡£ ¤³¤ì¤Ë¤è¤ê¡¢°ìÈÌŪ¤Ë³Æ¥æ¡¼¥¶ÄêµÁ¤Î±é»»»Ò¤ä±é»»»Ò·²¤´¤È¤Ë°ì¤Ä¤ÎÆÃ¼ì²½¤ò¹Ô¤¦¤À¤±¤Ç½½Ê¬¤È¤Ê¤ë¤¿¤á¡¢ÆÃ¼ì²½¤¬´Êñ¤Ë¤Ê¤ë¡£ °ìÊý¡¢ÆÃÄê¤Î±é»»»Ò¤òƱ¤¸·¿¤Î°ú¿ô¤Ë°Û¤Ê¤Ã¤¿ const/volatile ¤Î½¤¾þ»Ò¤ò¤Ä¤±¤¿¤ê¡¢¥ª¡¼¥Ð¡¼¥í¡¼¥É¤·¤¿±é»»»Ò¤ÎÊÖ¤êÃͤη¿¤¬°Û¤Ê¤ë¾ì¹ç¤Ë¤Ï¡¢¤è¤êºÙ¤«¤¤Áàºî¤¬É¬ÍפȤʤ롣 ¤è¤Ã¤Æ¡¢¸å¼Ô¤Î¥Æ¥ó¥×¥ì¡¼¥È¤Ç¤Ï¡¢°ú¿ô¤Î·¿¤Ï const/volatile ¤Î½¤¾þ»Ò¤âÊѹ¹¤»¤º¡¢È󻲾ȷ¿¤â¤½¤Î¤Þ¤Þ¤Ë¤¹¤ë¡£ ·çÅÀ¤Ï¾åµ­¤Î¤è¤¦¤Ê¥ª¡¼¥Ð¡¼¥í¡¼¥É¤·¤¿±é»»»Ò¤Î¤¿¤á¤Ë¡¢ºÇ°­¤Î¾ì¹ç½½Ï»¸Ä¤Î return_type_2 ¤ÎÆÃ¼ì²½¤¬É¬ÍפȤʤ뤫¤â¤·¤ì¤Ê¤¤¤³¤È¤Ç¤¢¤ë¡£

¥æ¡¼¥¶ÄêµÁ¤Î·¿ X¡¢Y¡¢Z ¤ËÂФ·¤Æ±é»»»Ò¤ò¥ª¡¼¥Ð¡¼¥í¡¼¥É¤·¤¿¤È¤¹¤ë¡£

Z operator+(const X&, const Y&);
Z operator-(const X&, const Y&);
¤½¤·¤Æ°Ê²¼¤Ç¤Ï¡¢º¸Â¦¤Î°ú¿ô¤Î·¿¤¬ X¤Ç¤¢¤ê¡¢±¦Â¦¤Î°ú¿ô¤Î·¿¤¬ Y ¤Ç¤¢¤ì¤Ð¡¢¤½¤Î¤è¤¦¤ÊÆó¹à±é»»¤Î·ë²Ì¤Î·¿¤Ï Z ¤Ç¤¢¤ë¤È¤¤¤¦ÆÃ¼ì²½¤Îµ­½Ò¤òÄɲ䷤Ƥ¤¤ë¡£
namespace boost { 
namespace lambda {
  
template<class Act> 
struct plain_return_type_2<arithmetic_action<Act>, X, Y> {
  typedef Z type;
};

}
}
¤³¤ÎÆÃ¼ì²½¤òÄêµÁ¤¹¤ë¤³¤È¤Ë¤è¤ê¡¢ BLL ¤ÏÀµ¤·¤¯¾åµ­¤ÎÆó¤Ä¤Î±é»»»Ò¤ÎÊÖ¤êÃͤη¿¤ò¿äÏÀ¤¹¤ë¤³¤È¤¬¤Ç¤­¤ë¡£ ÆÃ¼ì²½¤Ï¼çÍפʥƥó¥×¥ì¡¼¥È¤È¤È¤â¤Ë¡¢Ì¾Á°¶õ´Ö ::boost::lambda¤Ë ¸ºß¤·¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£ ´Êñ¤Î¤¿¤á¤Ë¡¢°Ê²¼¤ÎÎã¤Ç¤Ï¤³¤Î̾Á°¶õ´Ö¤ÎÄêµÁ¤Ï¾Êά¤¹¤ë¡£

±é»»»Ò¥°¥ë¡¼¥×¤ÎÆÃ¼ì²½¤Ë²Ã¤¨¤Æ¡¢ ¸Ä¡¹¤Î±é»»»Ò¤´¤È¤ËÆÃ¼ì²½¤ò¹Ô¤¦¤³¤È¤â²Äǽ¤Ç¤¢¤ë¡£ Î㤨¤Ð¡¢¿·¤·¤¯°ú¿ô¤Î·¿¤¬¡¢X ¤È Y ¤Ç¤¢¤ë»»½Ñ±é»»»Ò¤òÄɲä·¤¿¤È¤¹¤ë¡£

X operator*(const X&, const Y&);
Á´¤Æ¤Î»»½Ñ±é»»»Ò¤ËÂФ¹¤ëºÇ½é¤Îµ¬Â§¤Ç¤Ï¡¢ ÊÖ¤êÃͤη¿¤Ï Z ¤È»ØÄꤷ¤Æ¤¤¤ë¡£ ¤³¤ì¤Ï¡¢¤³¤Î¾ì¹ç¤Ë¤ÏÌÀ¤é¤«´Ö°ã¤Ã¤Æ¤¤¤ë¡£ ¤è¤Ã¤Æ¡¢¾ê;±é»»»Ò¤ËÂФ·¤Æ¼¡¤Î¤è¤¦¤Ë¿·¤·¤¤µ¬Â§¤òÄ󶡤¹¤ë¡£
template<> 
struct plain_return_type_2<arithmetic_action<multiply_action>, X, Y> {
  typedef X type;
};

ÆÃ¼ì²½¤Ë¤è¤ê¡¢°ú¿ô¤Î·¿¤«¤éÊÖ¤êÃͤη¿¤Ø¤ÎǤ°Õ¤Î¥Þ¥Ã¥Ô¥ó¥°¤òÄêµÁ¤¹¤ë¤³¤È¤¬¤Ç¤­¤ë¡£ ¼¡¤Î¤è¤¦¤Ë¡¢Í×ÁǤη¿¤ò¥Æ¥ó¥×¥ì¡¼¥È¤È¤·¤¿¿ô³ØÅª¤Ê¥Ù¥¯¥È¥ë¤¬¤¢¤Ã¤¿¤È¤¹¤ë¡£

template <class T> class my_vector;
Í×ÁǤη¿¤Î´Ö¤Ë²ÃË¡±é»»»Ò¤¬ÄêµÁ¤µ¤ì¤Æ¤¤¤ë¸Â¤ê¡¢ ¤¤¤«¤Ê¤ëÆó¤Ä¤Î my_vector ¤Î¥¤¥ó¥¿¥ó¥¹¤Î´Ö¤Ë¤â²ÃË¡±é»»»Ò¤¬ÄêµÁ¤µ¤ì¤ë¤È¤¹¤ë¡£ ¤µ¤é¤Ë¡¢¤½¤Î·ë²Ì¤Î my_vector ¤ÎÍ×ÁǤη¿¤Ï¡¢ Æó¤Ä¤Î my_vector ¤ÎÍ×ÁǤβÃË¡¤Î·ë²Ì¤Î·¿¤ÈƱ¤¸¤Ç¤¢¤ë¤È¤¹¤ë¡£ Î㤨¤Ð¡¢my_vector<int> ¤Èmy_vector<double> ¤Î²ÃË¡¤Î·ë²Ì¤Ï my_vector<double> ¤È¤Ê¤ë¡£ BLL ¤ÏÀ°¿ô¡¢ÉâÆ°¾®¿ô¡¢Ê£ÁÇ¿ô¤Î´Ö¤Ë¡¢ÁȤ߹þ¤ß¤Çɸ½à¤Î°ÅÌÛŪ¤Ê·¿ÊÑ´¹¤ò¹Ô¤Ê¤¦ÆÃÀ­¥¯¥é¥¹¤ò»ý¤Ã¤Æ¤¤¤ë¡£ BLL ¤Îµ¡Ç½¤òÍøÍѤ¹¤ì¤Ð¡¢¾åµ­¤Î²ÃË¡±é»»»Ò¤Ï¼¡¤Î¤è¤¦¤ËÄêµÁ¤Ç¤­¤ë¡£
template<class A, class B> 
my_vector<typename return_type_2<arithmetic_action<plus_action>, A, B>::type>
operator+(const my_vector<A>& a, const my_vector<B>& b)
{
  typedef typename 
    return_type_2<arithmetic_action<plus_action>, A, B>::type res_type;
  return my_vector<res_type>();
}

my_vector ¤Î²Ã»»¤Î·¿¿äÏÀ¤òÀµ³Î¤Ë¹Ô¤¦¤¿¤á¤Ë¡¢¼¡¤Î¤è¤¦¤ËÄêµÁ¤Ç¤­¤ë¡£

template<class A, class B> 
class plain_return_type_2<arithmetic_action<plus_action>, 
                           my_vector<A>, my_vector<B> > {
  typedef typename 
    return_type_2<arithmetic_action<plus_action>, A, B>::type res_type;
public:
  typedef my_vector<res_type> type;
};
BLL ¤Î¥Æ¥ó¥×¥ì¡¼¥È return_type_2 ¤Î¼Âºß¤¹¤ëÆÃ¼ì²½¤òºÆÍøÍѤ·¤Æ¤¤¤ë¡£ ¤½¤Î¤¿¤á¤Ë¤Ï¡¢°ú¿ô¤Î·¿¤¬»²¾È·¿¤Ç¤¢¤ë¤³¤È¤¬É¬ÍפǤ¢¤ë¡£

Table 2. Action types

+arithmetic_action<plus_action>
-arithmetic_action<minus_action>
*arithmetic_action<multiply_action>
/arithmetic_action<divide_action>
%arithmetic_action<remainder_action>
+unary_arithmetic_action<plus_action>
-unary_arithmetic_action<minus_action>
&bitwise_action<and_action>
|bitwise_action<or_action>
~bitwise_action<not_action>
^bitwise_action<xor_action>
<<bitwise_action<leftshift_action_no_stream>
>>bitwise_action<rightshift_action_no_stream>
&&logical_action<and_action>
||logical_action<or_action>
!logical_action<not_action>
<relational_action<less_action>
>relational_action<greater_action>
<=relational_action<lessorequal_action>
>=relational_action<greaterorequal_action>
==relational_action<equal_action>
!=relational_action<notequal_action>
+=arithmetic_assignment_action<plus_action>
-=arithmetic_assignment_action<minus_action>
*=arithmetic_assignment_action<multiply_action>
/=arithmetic_assignment_action<divide_action>
%=arithmetic_assignment_action<remainder_action>
&=bitwise_assignment_action<and_action>
=|bitwise_assignment_action<or_action>
^=bitwise_assignment_action<xor_action>
<<=bitwise_assignment_action<leftshift_action>
>>=bitwise_assignment_action<rightshift_action>
++pre_increment_decrement_action<increment_action>
--pre_increment_decrement_action<decrement_action>
++post_increment_decrement_action<increment_action>
--post_increment_decrement_action<decrement_action>
&other_action<address_of_action>
*other_action<contents_of_action>
,other_action<comma_action>