检查c 11中是否存在运算符的最佳方法

我需要检查给定的类是否定义了<<<(cls,ostream)运算符.如果是这样,我希望我的函数使用该函数将其写入ostringstream,否则应使用样板代码. 我知道这个问题曾经被问过.但是,我通常会找到一些自定义解决方案,这些解决方案并不总是能在我的编译器(clang)上运行.经过数小时的搜索,我终于找到了boost :: type_traits.我以前没有看过那里,因为我假设c 11已经复制了boost特质部门中的所有内容. 对我有用的解决方案是:

template <typename C>
std::string toString(C &instance) {
    std::ostringstream out;
    out << to_string<C, boost::has_left_shift<C, std::ostream>::value>::convert(ctx);
    return out.str();
}

将to_string定义为:

template <typename C, bool>
struct to_string {
    // will never get called
    static std::string convert(LuaContext &ctx) {}
};

template <typename C>
struct to_string<C, true> {
    static std::string convert(LuaContext &ctx) {
        return "convert(true) called.";
    }
};

template <typename C>
struct to_string<C, false> {
    static std::string convert(LuaContext &ctx) {
        return "convert(false) called.";
    }
};

所以我发布这个有两个原因:

>检查这是否是最明智的使用方法,或者看看其他人是否可以提出更好的解决方案(即,问题更多是出于对方法的好奇,而不是“这是否行得通?”-已经对我有用)
>发布此信息可以节省其他人的搜索时间,以防其他人也需要执行类似的操作.
>作为一个更普遍的问题-有时特质类似乎返回std :: true_type或std :: false_type(嗯,至少对于非增强类而言).其他时候他们是笨蛋.有这种差异的原因吗?如果boost:has_left_shift返回的是类型而不是布尔值,那么我可能只有一个to_string结构.

解决方法:

速成C 11 SFINAE:

template<typename T,
         typename = decltype(
           std::declval<std::ostream&>() << std::declval<T const&>()
         )
>
std::string toString(T const& t)
{
    std::ostringstream out;
    // Beware of no error checking here
    out << t;
    return out.str();
}

template<typename T,
         typename... Ignored
>
std::string toString(T const& t, Ignored const&..., ...)
{
    static_assert( sizeof...(Ignored) == 0
                 , "Incorrect usage: only one parameter allowed" );
    /* handle any which way here */
}

如果需要,还可以检查流的返回类型<< val确实可以转换为std :: ostream&amp ;:

template<typename T,
         typename Result = decltype(
           std::declval<std::ostream&>() << std::declval<T const&>()
         ),
         typename std::enable_if<
             std::is_convertible<Result, std::ostream&>::value,
             int
         >::type = 0
>

对于不太脏的解决方案,我将引入is_stream_insertable特征,该特征可以利用此处使用的相同技巧.

请注意,std :: integral_constant< bool,B>有一个bool转换运算符,这也许可以解释您所观察到的一些事情.我也不建议将C 11标准类型和特征与Boost混合使用:不要将std :: true_type与boost :: true_type混合使用!这并不是说您不应该使用例如Boost.TypeTraits与C 11完全兼容,但请尝试保持一致,并且一次仅使用两个之一.

上一篇:JavaScript-这是es6赋值运算符?


下一篇:c-为什么当我强制转换为“ long”时会调用“ operator bool()”?