C ++检测是否存在按名称接受特定类型的函数
C++ Detect if there exists a function by name that accepts a particular type
我想检测给定类型是否有插入运算符。通常我会检查是否存在具有正确签名的重载函数。假设我有一个 class A,那么
template<typename T>
struct insert_operator_type
{
using type = typename std::ostream&(*)(std::ostream&, const T&);
};
...
std::is_same<
decltype(static_cast<typename insert_operator_type<A>::type> (&operator<<)),
std::ostream&(*)(std::ostream&, A const&)
>::value
会告诉我它们是一样的,我可以推断出运算符存在。然而,使用 operator<< 类型 B 可能会解析为类型 A。比如
template<typename T>
class A
{
public:
T* type1 = nullptr;
};
typedef A<int> BImpl;
class B : public BImpl
{
public:
B() {}
};
template<typename T>
std::ostream& operator<<(std::ostream& os, const A<T>& a)
{
os << "printing A<T>" << std::endl;
return os;
}
现在我可以
B b;
std::cout << b << std::endl;
但是没有
std::ostream&(*)(std::ostream&, B const&)
相反,编译器发现使用 BImpl 版本,并且惯用法无法识别 B 有插入运算符。
我能否确定是否存在一个重载函数,以至于该函数可能不是为特定类型指定的,而是对于给定类型将转换为的某些类型?
您可能只想使用 SFINAE 检查执行插入的整个表达式是否有效。
// std::void_t in C++1z
template <class...>
using void_t = void;
template <class, class = void_t<>>
struct can_be_ostreamed : std::false_type { };
template <class T>
struct can_be_ostreamed<T, void_t<
decltype(std::declval<std::ostream&>() << std::declval<T>())
>> : std::true_type { };
我想检测给定类型是否有插入运算符。通常我会检查是否存在具有正确签名的重载函数。假设我有一个 class A,那么
template<typename T>
struct insert_operator_type
{
using type = typename std::ostream&(*)(std::ostream&, const T&);
};
...
std::is_same<
decltype(static_cast<typename insert_operator_type<A>::type> (&operator<<)),
std::ostream&(*)(std::ostream&, A const&)
>::value
会告诉我它们是一样的,我可以推断出运算符存在。然而,使用 operator<< 类型 B 可能会解析为类型 A。比如
template<typename T>
class A
{
public:
T* type1 = nullptr;
};
typedef A<int> BImpl;
class B : public BImpl
{
public:
B() {}
};
template<typename T>
std::ostream& operator<<(std::ostream& os, const A<T>& a)
{
os << "printing A<T>" << std::endl;
return os;
}
现在我可以
B b;
std::cout << b << std::endl;
但是没有
std::ostream&(*)(std::ostream&, B const&)
相反,编译器发现使用 BImpl 版本,并且惯用法无法识别 B 有插入运算符。
我能否确定是否存在一个重载函数,以至于该函数可能不是为特定类型指定的,而是对于给定类型将转换为的某些类型?
您可能只想使用 SFINAE 检查执行插入的整个表达式是否有效。
// std::void_t in C++1z
template <class...>
using void_t = void;
template <class, class = void_t<>>
struct can_be_ostreamed : std::false_type { };
template <class T>
struct can_be_ostreamed<T, void_t<
decltype(std::declval<std::ostream&>() << std::declval<T>())
>> : std::true_type { };