检查c ++ 11中是否存在运算符的最佳方法 [英] best way to check for existence of an operator in c++11

查看:124
本文介绍了检查c ++ 11中是否存在运算符的最佳方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I need to check if a given class has the <<(cls, ostream) operator defined or not. If so, I want my function to use that to write to ostringstream, otherwise boilerplate code should be used.

我知道这个问题曾经被问过.但是,我通常会找到一些定制解决方案,这些解决方案并不总是在我的编译器(clang ++)上起作用.经过数小时的搜索,我终于找到了boost :: type_traits.我以前没看过那里,因为我假设c ++ 11已经复制了boost特质部门中的所有内容.

I know this question has been asked before. However, I generally find custom solutions that don't always work on my compiler (clang++). After many hours of searching, I finally found out that boost::type_traits. I hadn't look there previously, because I had assumed c++11 already copied everything in the traits department that boost had.

最适合我的解决方案是:

The solution that worked for me was to do:

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.";
    }
};

所以我发布此消息有两个原因:

So I'm posting this for two reasons:

  1. 请检查这是否是最合理的方法,或者看看其他人是否可以提出更好的解决方案(即,问题更多是出于对方法的好奇,而不是这是否行得通?"-它已经有效对我来说)

  1. Check if this is the sanest method to use, or see if someone else can suggest an even better solution (i.e. the question is more out of curiosity of approach than "will this work?" -- it already works for me)

发布此信息可以节省其他人的搜索时间,以防其他人也需要做类似的事情.

Post this up to save someone else hours of searching in case she/he also needs to do something similar.

作为一个更普遍的问题-有时特征类似乎返回std :: true_type或std :: false_type(好吧,至少对于非增强类而言).其他时候他们是笨蛋.有这种差异的原因吗?如果boost:has_left_shift返回的是类型而不是bool,那么我可能只有一个to_string结构.

As a more general question -- sometimes trait classes appear to return std::true_type or std::false_type (well, at least for non-boost classes). Other times they are bools. Is there a reason for this discrepancy? If boost:has_left_shift returned a type instead of a bool, then I could have just a single to_string struct.

推荐答案

速成C ++ 11 SFINAE:

Quick-and-dirty 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 */
}

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

If you want you can also check that the return type of stream << val is indeed convertible to std::ostream&:

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特征,该特征可以利用此处使用的相同技巧.

As for a not so quick-and-dirty solution I'd introduce an is_stream_insertable trait, which implementation can make use of the very same tricks used here.

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

Be aware that std::integral_constant<bool, B> has a conversion operator to bool, this might explain some of the things you have observed. I also do not recommend mixing the C++11 Standard types and traits with Boost: don't mix up std::true_type with boost::true_type! Which is not to say that you shouldn't use e.g. Boost.TypeTraits at all with C++11, but try to be consistent and only use one of two at a time.

这篇关于检查c ++ 11中是否存在运算符的最佳方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆