为什么非专业模板胜过部分专业模板?

我正在尝试创建一个模板化can_stream结构,该结构继承自
std::false_typestd::true_type取决于是否operator<<为 type 定义T

#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

因为:

  • 运算符同时<<存在于intS(因此decltype(...)格式良好)。
  • 部分专业化模板比非专业化模板更好的匹配。

但是,它产生:

  0
  0
  0

为什么?

回答

运算符同时<<存在于intS(因此decltype(...)格式良好)。

decltype( operator<<( std::declval< std::ostream& >(), std::declval< T const& >()))std::ostream&,在默认值Enablevoid

没有匹配。

你可以试试

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<<()函数。但不适用于intfor 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带有隐式 operator 的其他类型<<)或者运算符<<是否具体可用,请见。

  • `decltype(std::declval<std::ostream&>() << std::declval<T const&>(), void())` works for `int` too though
  • @largest_prime_is_463035818 I think that's because the form of `operator <<`. `std::declval< std::ostream& >() << std::declval< T const& >()` should makes it work

以上是为什么非专业模板胜过部分专业模板?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>