我们有一个子项目'commonUtils',具有许多的通用代码段使用跨父项目。一个这样的有趣的东西我看到的是:-

/*********************************************************************
If T is polymorphic, the compiler is required to evaluate the typeid 
stuff at runtime, and answer will be true.  If T is non-polymorphic, 
the compiler is required to evaluate the typeid stuff at compile time, 
whence answer will remain false
*********************************************************************/
template <class T> 
bool isPolymorphic() { 
   bool answer=false; 
   typeid(answer=true,T()); 
   return answer; 
}

我相信评论,并认为这是一个相当有趣的模板,但它不是 用于整个项目。我尝试使用这样的只是好奇...

class PolyBase {
public:
   virtual ~PolyBase(){}
};

class NPolyBase {
public:
   ~NPolyBase(){}
};


if (isPolymorphic<PolyBase>())
  std::cout<<"PolyBase = Polymorphic\n";
if (isPolymorphic<NPolyBase>())
  std::cout<<"NPolyBase = Also Polymorphic\n";

但没有那些曾经返回正确的。MSVC2005年没有给出警告,但科莫警告typeid表达没有任何影响。部分5.2.8在C++标准不会说什么,喜欢什么样的评论说:即typeid是评估在编译的时间不多态的类型和运行为的多晶型类型。

1)因此,我想评论具有误导性/纯的错误或因为提交人的这种代码是一个相当高C++编程,我失去了一些东西?

2)另一方面,我想知道如果我们可以测试是否类是多态性(至少有一个虚拟的功能)使用一些技术?

3)如果一个人想要知道,如果一类是多态?猜猜;为获得启动地址的一类通过使用 dynamic_cast<void*>(T) (作为 dynamic_cast 仅适用于多晶型类)。

在等待你的意见。

在此先感谢,

有帮助吗?

解决方案

我无法想象任何可能的方式如何那typeid的可以用来检查类型是多态的。它甚至不能用来断言它是,因为typeid运算可以在任何类型的工作。 升压这里有一个实现。至于为什么它可能是必要的 - 一个情况下,我知道的是Boost.Serialization库。如果要保存非多态类型,那么你可以将它保存。如果在保存多态之一,你必须使用的typeid以获取其动态类型,然后调用该类型的序列化方法(在某些表了寻找它)。

更新:看来我其实是错误的。考虑该变体:

template <class T> 
bool isPolymorphic() { 
    bool answer=false;
    T *t = new T();
    typeid(answer=true,*t); 
    delete t;
    return answer; 
}

这实际上确实工作作为顾名思义,正是根据注释在原始代码段。内部typeid的表达,如果它“不指定多态类类型的左值”(STD 3.2 / 2)不进行评价。因此,在上述情况下,如果T是不是多态的,所述typeid的表达不进行评价。如果T是多态的,那么* t是确实左值多态型的,所以整个表达式必须被评估。

现在,你原来的例子仍然是错误的:-)。它使用T(),不*t。和T()创建的右值(STD 3.10 / 6)。因此,它仍产生不“多态类的左值”。

的表达

这是相当有趣的把戏。在另一方面,它的实用价值是比较有限的 - 因为虽然升压:: is_polymorphic给你一个编译时间常数,这个人给你一个运行时间值,所以你不能实例化多态和非多态类型不同的代码

其他提示



class PolyBase {
public:   
    virtual ~PolyBase(){}
};

class NPolyBase {
public:
    ~NPolyBase(){}
};

template<class T>
struct IsPolymorphic
{
    struct Derived : T {
        virtual ~Derived();
    };
    enum  { value = sizeof(Derived)==sizeof(T) };
};


void ff()
{
    std::cout << IsPolymorphic<PolyBase >::value << std::endl;
    std::cout << IsPolymorphic<NPolyBase>::value << std::endl;
}

由于C ++ 11,这是目前在<type_traits>标头,如std::is_polymorphic可用。它可用于这样的:

struct PolyBase {
  virtual ~PolyBase() {}
};

struct NPolyBase { 
  ~NPolyBase() {}
};

if (std::is_polymorphic<PolyBase>::value)
  std::cout << "PolyBase = Polymorphic\n";
if (std::is_polymorphic<NPolyBase>::value)
  std::cout << "NPolyBase = Also Polymorphic\n";

此打印只是 “多碱=多态性”。

一个可以使用的事实是:

  1. dynamic_cast 失败在编制时间,如果说法不是一个多晶型类。因此,它可以被用于与SFINAE.
  2. dynamic_cast<void*> 是一个有效的投返回的地址 完整的 polymorpic对象。

因此,在C++11:

#include <iostream>
#include <type_traits>

template<class T>
auto is_polymorphic2_test(T* p) -> decltype(dynamic_cast<void*>(p), std::true_type{});

template<class T>
auto is_polymorphic2_test(...) -> std::false_type;

template<class T>
using is_polymorphic2 = decltype(is_polymorphic2_test<T>(static_cast<T*>(0)));

struct A {};
struct B { virtual ~B(); };

int main() {
    std::cout << is_polymorphic2<A>::value << '\n'; // Outputs 0.
    std::cout << is_polymorphic2<B>::value << '\n'; // Outputs 1.
}

我有点糊涂了这里,并且我希望能得到这样的回答一些意见解释,我错过了什么。

当然,如果你想找出一类是多态的,所有你需要做的就是询问是否支持dynamic_cast,是不是啊?

template<class T, class> struct is_polymorphic_impl   : false_type {};
template<class T> struct is_polymorphic_impl
    <T, decltype(dynamic_cast<void*>(declval<T*>()))> : true_type {};

template<class T> struct is_polymorphic :
    is_polymorphic_impl<remove_cv_t<T>, void*> {};

任何人都可以指出在此实现的一个漏洞?我想必须有一个,或者一定是一个在过去的某个时间,因为的升压文档继续声称is_polymorphic‘不能在C ++语言来实现可移植’。

但是,“便携”是怎样的一个黄鼠狼字的,对不对?也许他们只是暗指MSVC怎么不支持表达式SFINAE,或者一些方言,如嵌入式C ++不支持dynamic_cast。也许当他们说:“C ++语言”,他们说“一个C ++语言的最小公分母的子集。”但我有一种挥之不去的怀疑,也许他们的意思,他们说什么,的一个谁失去了一些东西。

在OP的typeid办法(修订通过后的答案用一个左不右值)也似乎很好,但当然这不是constexpr,它需要真正构建Tde,这可能是超贵。所以这dynamic_cast做法似乎更好......除非它不适用于某些原因。想法?

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top