2010-05-05 73 views
1

我有一个定义子类型的模板类。我试图将二进制operator+定义为模板函数,但编译器无法解析operator+的模板版本。运算符+用于模板类的子类型

#include <iostream> 
template<typename other_type> 
struct c { 
    c(other_type v) : cs(v) {} 
    struct subtype { subtype(other_type v) : val(v) {} other_type val; } cs; 
}; 

template<typename other_type> 
typename c<other_type>::subtype operator+(const typename c<other_type>::subtype& left, 
         const typename c<other_type>::subtype& right) 
{ return typename c<other_type>::subtype(left.val + right.val); } 

// This one works 
// c<int>::subtype operator+(const c<int>::subtype& left, 
//   const c<int>::subtype& right) 
// { return c<int>::subtype(left.val + right.val); } 

int main() 
{ 
    c<int> c1 = 1; 
    c<int> c2 = 2; 
    c<int>::subtype cs3 = c1.cs + c2.cs; 
    std::cerr << cs3.val << std::endl; 
} 

我想原因是因为所以它的查找operator+<int>,而不是operator+编译器(G ++ 4.3)无法猜测的模板类型。

这是什么原因?你能提出什么优雅的解决方案?

+0

的原因是你已经按照C++标准14.8.2.4/4这里nondeduced上下文。 – 2010-05-05 20:21:25

回答

4

您的怀疑是正确的。编译器不知道other_type是什么。它不能从论据中推论出来。这种形式通常过于宽松,无法提供所需的信息。考虑

template<typename other_type> 
struct c { 
    c(other_type v) : cs(v) {} 
    typedef int subtype; 
}; 

如果你要传递一个int,那么任何的c<T>将适合该法案,因为他们都有类型int。在嵌套类的特定情况下,它可能是可能的,但即使这样也不是唯一的。想象一下,在c<float>你可以把typedef c<int> subtype;,然后c<float>::subtypec<int>::subtype将符合法案。

早在预标准时,存在着的模板的问题是,在特定的约翰·斯派塞没有经过一个列表,并发明了合理的解决方案。这是一个这样的问题,并且发现它不值得麻烦。你总是明确地需要提供论据 - 它从来没有被推论过。

你可以更改您的代码此

template<typename other_type> 
struct subtype { 
    subtype(other_type v) : val(v) {} 
    other_type val; 
}; 

template<typename other_type> 
struct c { 
    c(other_type v) : cs(v) {} 
    subtype<other_type> cs; 
}; 

template<typename other_type> 
subtype<other_type> operator+(const subtype<other_type>& left, 
         const subtype<other_type>& right) 
{ return subtype<other_type>(left.val + right.val); } 

或在本

template<typename other_type> 
struct c { 
    c(other_type v) : cs(v) {} 
    struct subtype { 
    subtype(other_type v) : val(v) {} other_type val; 

    /* note: don't forget friend! */ 
    friend subtype operator+(const subtype& left, 
         const subtype& right) 
    { return subtype(left.val + right.val); } 
    } cs; 
}; 
+0

+1被击败;无论如何,这比我的要好。 – 2010-05-05 20:16:09

+0

@Charles,谢谢。赞赏 – 2010-05-05 20:23:27

+0

第二个报告错误(阴影other_type),如果我更改模板的名称键入它提供了相同的错误之前(而且似乎这个朋友操作+的类型应该是一样的原之一)。 – baol 2010-05-05 20:27:41