为什么非专业化的模板胜过部分专业化的模板?
Why does an unspecialised template win over a partially specialised one?
我正在尝试创建一个继承自的模板化 can_stream
结构
std::false_type
或 std::true_type
取决于是否为类型 T
.
定义了 operator<<
#include <iostream>
struct S {
int i;
};
std::ostream& operator<< (std::ostream& os, S const& s) {
os << s.i << std::endl;
return os;
};
struct R {
int i;
};
template<
typename T,
typename Enable = void
> struct can_stream : std::false_type {
};
template<
typename T
> struct can_stream< T, decltype( operator<<( std::declval< std::ostream& >(), std::declval< T const& >())) > : std::true_type {
};
int main() {
std::cout << can_stream< int >::value << std::endl;
std::cout << can_stream< S >::value << std::endl;
std::cout << can_stream< R >::value << std::endl;
}
我以为上面的程序会产生
1
1
0
因为:
- 运算符
<<
对于 int
和 S
都存在(因此 decltype(...)
格式正确)。
- 部分专用模板比非专用模板更匹配。
然而,它产生:
0
0
0
为什么?
operator <<
exists for both int
and S
(so decltype(...)
is well formed).
但是 decltype( operator<<( std::declval< std::ostream& >(), std::declval< T const& >()))
是 std::ostream&
,其中 Enable
的默认值是 void
。
没有匹配项。
你可以试试
template<
typename T // ........................................................................................VVVVVVVVV
> struct can_stream< T, decltype( operator<<( std::declval< std::ostream& >(), std::declval< T const& >()), void() ) > : std::true_type {
};
或者,如果你可以使用 C++17,那么 std::void_t
,
template<
typename T // ......VVVVVVVVVVVV
> struct can_stream< T, std::void_t<decltype( operator<<( std::declval< std::ostream& >(), std::declval< T const& >()))> > : std::true_type {
};
这解决了 S
的问题,因为 S
有一个 operator<<()
函数。但不适用于 int
,因为对于 int
,运算符未定义为函数。所以,对于int
,你要模拟使用
template<
typename T // ...........................................................VVVV
> struct can_stream< T, std::void_t<decltype( std::declval< std::ostream& >() << std::declval< T const& >() )> > : std::true_type {
};
如果你喜欢检查函数 operator<<()
的存在(但这不适用于 int
和其他带有隐式运算符 <<
的类型)或者如果运算符<<
具体可用
我正在尝试创建一个继承自的模板化 can_stream
结构
std::false_type
或 std::true_type
取决于是否为类型 T
.
operator<<
#include <iostream>
struct S {
int i;
};
std::ostream& operator<< (std::ostream& os, S const& s) {
os << s.i << std::endl;
return os;
};
struct R {
int i;
};
template<
typename T,
typename Enable = void
> struct can_stream : std::false_type {
};
template<
typename T
> struct can_stream< T, decltype( operator<<( std::declval< std::ostream& >(), std::declval< T const& >())) > : std::true_type {
};
int main() {
std::cout << can_stream< int >::value << std::endl;
std::cout << can_stream< S >::value << std::endl;
std::cout << can_stream< R >::value << std::endl;
}
我以为上面的程序会产生
1
1
0
因为:
- 运算符
<<
对于int
和S
都存在(因此decltype(...)
格式正确)。 - 部分专用模板比非专用模板更匹配。
然而,它产生:
0
0
0
为什么?
operator
<<
exists for bothint
andS
(sodecltype(...)
is well formed).
但是 decltype( operator<<( std::declval< std::ostream& >(), std::declval< T const& >()))
是 std::ostream&
,其中 Enable
的默认值是 void
。
没有匹配项。
你可以试试
template<
typename T // ........................................................................................VVVVVVVVV
> struct can_stream< T, decltype( operator<<( std::declval< std::ostream& >(), std::declval< T const& >()), void() ) > : std::true_type {
};
或者,如果你可以使用 C++17,那么 std::void_t
,
template<
typename T // ......VVVVVVVVVVVV
> struct can_stream< T, std::void_t<decltype( operator<<( std::declval< std::ostream& >(), std::declval< T const& >()))> > : std::true_type {
};
这解决了 S
的问题,因为 S
有一个 operator<<()
函数。但不适用于 int
,因为对于 int
,运算符未定义为函数。所以,对于int
,你要模拟使用
template<
typename T // ...........................................................VVVV
> struct can_stream< T, std::void_t<decltype( std::declval< std::ostream& >() << std::declval< T const& >() )> > : std::true_type {
};
如果你喜欢检查函数 operator<<()
的存在(但这不适用于 int
和其他带有隐式运算符 <<
的类型)或者如果运算符<<
具体可用