为什么这些条件不适用于模板类型?

why shouldn't these conditions work for template types?

作为我的 ,我正在尝试建立一个条件来检查两种类型,检查我是否应该 dynamic_cast。 我有以下条件:

#define can_dynamic_cast(FROM, TO) \
                                can_cast(FROM, TO) && \
                                !std::is_same<FROM, TO>::value && \
                                std::is_class<TO>::value && \
                                !std::is_const<FROM>::value && \ 
                                std::is_base_of<TO, FROM>::value

它不适用于以下基本检查,can_dynamic_cast 将 return 为真!!!

 static_assert(!can_dynamic_cast(int, int), "didn't expecting dynamic cast, but could!")

出于绝望,我降到了以下条件,但仍然没有希望!

#define can_dynamic_cast(FROM, TO)   \
                                    std::is_convertible<FROM, TO>::value && \
                                    std::is_class<TO>::value && \
                                    std::is_class<FROM>::value 

以上条件是最基本的条件,can_dynamic_cast会returntrue(int, int),这是不应该的!!!

问题

1) 我没看错什么?

总结一下评论中给出的解决方案和答案:(感谢T.C.和AntonSavin)

你的宏不是完全错误,但它是一个宏。预处理器简单地用宏的内容替换宏调用:

 static_assert(!can_dynamic_cast(int, int), "...");
 // =>
 static_assert(!std::is_convertible<int, int>::value && 
                std::is_class<int>::value &&
                std::is_class<int>::value , "...");

因此,只有第一个值被取反,这会产生意外行为。

要解决这个问题,您必须在宏定义或宏调用中添加方括号:

#define can_dynamic_cast(FROM, TO) \
         ( std::is_convertible<FROM, TO>::value && \
           std::is_class<TO>::value && \
           std::is_class<FROM>::value )
// or

static_assert(!(can_dynamic_cast(int, int)), "...");

更好的解决方案而不是更长的解决方案是创建自己的类型特征 class:

template <class FROM, class TO>
struct can_dynamic_cast : std::integral_constant< bool,
    std::is_convertible<FROM, TO>::value && 
    std::is_class<TO>::value &&
    std::is_class<FROM>::value > {};

static_assert(!can_dynamic_cast<int, int>::value, "...");

它不太容易出错,因为它在元函数调用中遵循 c++ 语法并且不需要额外的括号。