对不起,这听起来像是一个常见的问题,就我看来,我无法找到问题的答案。最近的帖子是这一个:Template Specialization for basic POD only
假设我有一个类template <class T> class A {...};
,我想将operator +重载为内部二元运算符(A类型的两个对象),并作为混合二元运算符(类型A和数字POD类型的对象)重载
理想情况下,我想写的是:
#include <type_traits>
using namespace std;
// Declare/fine template
template <class T> class A {...};
// Internal binary operator
template < class T, class U >
A< typename common_type<T,U>::type >
operator+ ( const A<T> &a, const A<U> &a ) { ... }
// Mixed binary operator
template < class T, class U >
A< typename common_type<T,U>::type >
operator+ ( const A<T> &a, const U &b ) { ... }
但似乎第二个定义与第一个定义相冲突。使用第二个定义,我知道如何确保U是一个数字POD类型,这不是重点。如果我这样做,问题是如果它是A,我无法知道U中包含什么底层模板类型。
如果我的问题不够明确,请告诉我,并提前致谢! :)
编辑:HTML过滤器消除了模板规范,在我的最后一句“U如果它是A<T>
”中。简而言之,我说T是隐藏的。
答案 0 :(得分:2)
你可以使用一个小帮手特征来区分A
的特殊化与更一般的类型:
#include <type_traits>
// "A" template
template <typename> class A {};
// Traits for "A-ness":
template <typename> struct is_a : std::false_type { };
template <typename T> struct is_a<A<T>> : std::true_type { };
// Operators:
template <class T, class U>
A<typename std::common_type<T, U>::type>
operator+(const A<T> & a, const A<U> & b);
template <class T, class U,
typename = typename std::enable_if<!is_a<U>::value>::type>
A<typename std::common_type<T, U>::type>
operator+(const A<T> & a, const U & b);
这排除了可行集的第二次过载,因此当只需要第一次过载时,确定第二次过载的返回类型的问题永远不会出现。
(这是在默认模板参数中使用enable_if
来控制重载集的示例。)
答案 1 :(得分:1)
你可以写一个SFINAE友好的common_type
- 我个人在营地,这个特征应该几乎总是SFINAE。即:
// Black hole metafunction that eats everything
template<typename...> struct void_ { using type = void; };
template<typename... T>
using Void = typename void_<T...>::type;
// Due to std::common_type being variadic we need to
// pass a variadic pack around
template<typename... T> struct list {};
// Actually defined, but with no member types for SFINAE purposes
template<typename Sequence, typename Sfinae = void>
struct common_type_impl {};
template<typename... T>
struct common_type_impl<list<T...>, Void<typename std::common_type<T...>::type>>
: std::common_type<T...> {};
template<typename... T> struct common_type: common_type_impl<list<T...>> {};
现在,当A<T>
和U
之间没有共同类型时,重叠将从候选人列表中删除,而不是大声抱怨。
还可以完全替换std::common_type
,因为它计算的结果有自己的问题,如DR 2141中所述。我不会概述一个替代品,因为不清楚什么是更好的解决方案,特别是我认为提议的DR分辨率更差。