首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在c++11中检查操作符是否存在的最佳方法

在c++11中检查操作符是否存在的最佳方法
EN

Stack Overflow用户
提问于 2012-10-19 18:43:46
回答 1查看 2.7K关注 0票数 3

我需要检查给定的类是否定义了<<(cls, ostream)运算符。如果是这样的话,我希望我的函数使用它来写入ostringstream,否则应该使用样板代码。

我知道以前有人问过这个问题。但是,我通常会发现自定义解决方案并不总是适用于我的编译器(clang++)。经过几个小时的搜索,我终于发现了boost::type_traits。我以前没有看过那里,因为我认为c++11已经复制了boost的特性部门的所有东西。

对我有效的解决办法是:

代码语言:javascript
复制
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定义为:

代码语言:javascript
复制
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.";
    }
};

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

  1. 检查这是否是最明智的方法,或者看看其他人是否能提出更好的解决方案(也就是说,这个问题更多的是出于对方法的好奇,而不是“这能成功吗?”--它已经对我起作用了)
  2. 发布这篇文章是为了节省其他人的搜索时间,以防她/他也需要做类似的事情。
  3. 作为一个更普遍的问题--有时特征类似乎返回std::true_type或std::false_type (嗯,至少对于非boost类是这样)。其他时候,他们都是傻瓜。有什么原因造成这种差异吗?如果boost:has_left_shift返回一个类型而不是一个bool,那么我可以只返回一个to_string结构。
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-10-19 20:54:02

快速和肮脏的C++11 SFINAE:

代码语言:javascript
复制
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 */
}

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

代码语言:javascript
复制
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_typeboost::true_type!这并不是说您不应该在C++11中使用例如C++11,而是尝试保持一致性,一次只使用两个中的一个。

票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12980508

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档