帮助了解类型特征

发布于 2024-08-17 15:25:18 字数 935 浏览 11 评论 0原文

假设我们有以下模板类,

template<typename T> class Wrap { /* ... */ };

我们无法更改 Wrap。这很重要。

假设有从 Wrap 派生的类。例如,

class NewInt  : public Wrap<int>     { /* ... */ };
class MyClass : public Wrap<myclass> { /* ... */ };
class Foo     : public Wrap<Bar>     { /* ... */ };

我们也无法更改这些类。以上所有课程均为第三方。他们不是我的。

我需要以下编译时type_traits

template<class T>
struct is_derived_from_Wrap { 
     static const bool value = /* */;
};

我需要什么?

assert(is_derived_from_Wrap<Int>::value == true);  // Indeed I need static assert
assert(is_derived_from_Wrap<MyClass>::value == true);
assert(is_derived_from_Wrap<char>::value == false);
struct X {};
assert(is_derived_from_Wrap<X>::value == false);

Suppose we have the following template class

template<typename T> class Wrap { /* ... */ };

We can not change Wrap. It is important.

Let there are classes derived from Wrap<T>. For example,

class NewInt  : public Wrap<int>     { /* ... */ };
class MyClass : public Wrap<myclass> { /* ... */ };
class Foo     : public Wrap<Bar>     { /* ... */ };

We can not change these classes too. All classes above is 3rd party. They are not mine.

I need the following compile time type_traits:

template<class T>
struct is_derived_from_Wrap { 
     static const bool value = /* */;
};

What do I need?

assert(is_derived_from_Wrap<Int>::value == true);  // Indeed I need static assert
assert(is_derived_from_Wrap<MyClass>::value == true);
assert(is_derived_from_Wrap<char>::value == false);
struct X {};
assert(is_derived_from_Wrap<X>::value == false);

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

情场扛把子 2024-08-24 15:25:18

您可以使用 SFINAE 来完成此操作,但如果您不知道发生了什么,它会很神奇......

template<typename T> class Wrap { };

struct myclass {};
struct X {};

class Int     : public Wrap<int>     { /* ... */ };
class MyClass : public Wrap<myclass> { /* ... */ };

template< typename X >
struct is_derived_from_Wrap
{
  struct true_type { char _[1]; };
  struct false_type { char _[2]; };

  template< typename U >
    static true_type test_sfinae( Wrap<U> * w);
  static false_type test_sfinae( ... );

  enum { value = sizeof( test_sfinae( (X*)(0) ) )==sizeof(true_type) };
};


#include <iostream>
#define test(X,Y) std::cout<<( #X " == " #Y )<<"  : "<<( (X)?"true":"false") <<std::endl;

int main()
{
  test(is_derived_from_Wrap <Int>::value, true);
  test(is_derived_from_Wrap <MyClass>::value, true);
  test(is_derived_from_Wrap <char>::value, false);
  test(is_derived_from_Wrap <X>::value, false);
}

这给出了预期的输出

is_derived_from_Wrap <Int>::value == true  : true
is_derived_from_Wrap <MyClass>::value == true  : true
is_derived_from_Wrap <char>::value == false  : false
is_derived_from_Wrap <X>::value == false  : false

我的代码有一些问题。如果类型是 Wrap,它也会返回 true。

assert(  is_derived_from_Wrap< Wrap<char> >::value == 1 );

如果需要的话,这个问题可以使用更多的 SFINAE 魔法来解决。

如果派生不是公共派生(即私有或受保护),它将返回 false

struct Evil : private Wrap<T> { };
assert( is_derived_from_Wrap<Evil>::value == 0 );

我怀疑这无法修复。 (但我可能是错的)。但我怀疑公共继承就足够了。

You can do this using SFINAE but its kind of magical if you dont know whats going on...

template<typename T> class Wrap { };

struct myclass {};
struct X {};

class Int     : public Wrap<int>     { /* ... */ };
class MyClass : public Wrap<myclass> { /* ... */ };

template< typename X >
struct is_derived_from_Wrap
{
  struct true_type { char _[1]; };
  struct false_type { char _[2]; };

  template< typename U >
    static true_type test_sfinae( Wrap<U> * w);
  static false_type test_sfinae( ... );

  enum { value = sizeof( test_sfinae( (X*)(0) ) )==sizeof(true_type) };
};


#include <iostream>
#define test(X,Y) std::cout<<( #X " == " #Y )<<"  : "<<( (X)?"true":"false") <<std::endl;

int main()
{
  test(is_derived_from_Wrap <Int>::value, true);
  test(is_derived_from_Wrap <MyClass>::value, true);
  test(is_derived_from_Wrap <char>::value, false);
  test(is_derived_from_Wrap <X>::value, false);
}

This gives the expected output

is_derived_from_Wrap <Int>::value == true  : true
is_derived_from_Wrap <MyClass>::value == true  : true
is_derived_from_Wrap <char>::value == false  : false
is_derived_from_Wrap <X>::value == false  : false

There are a couple of gotchas with my code. It will also return true if the type is a Wrap.

assert(  is_derived_from_Wrap< Wrap<char> >::value == 1 );

This can probably be fixed using a bit more SFINAE magic if needed.

It will return false if the derivation is not a public derivation (i.e is private or protected )

struct Evil : private Wrap<T> { };
assert( is_derived_from_Wrap<Evil>::value == 0 );

I suspect this can't be fixed. (But I may be wrong ). But I suspect public inheritance is enough.

千笙结 2024-08-24 15:25:18

在一般情况下,您需要进行一些相当复杂的模板元编程来确定一个类 X 是否派生自另一个类 Y。基本上,X 派生自 Y,如果:

  1. Y 可以隐式转换为 X
  2. X 和 Y 不是同一类型

Andrei Alexandrescu 解释道如何做到这一点(以及许多其他模板技巧)在他的书“Modern C++ Design”中。

您可以在 Loki 库或 uSTL 实现,均由 Alexandrescu 编写。

You need to do some fairly involved template metaprogramming to determine if one class X is derived from another Y, in the general case. Basically X derives from Y if:

  1. Y can be implicitly converted to X
  2. X and Y are not the same type

Andrei Alexandrescu explains how to do this (along with many other template tricks) in his book "Modern C++ Design".

You can find code which solves your problem either in the Loki library, or the uSTL implementation, both written by Alexandrescu.

厌味 2024-08-24 15:25:18

以下内容确定某物是否换行:

template<class T>
struct is_Wrap { static const bool value = false; };

template<typename T> 
struct is_Wrap< Wrap<T> > { static const bool value = true; };

由于派生是 Is-A 关系,因此从 Wrap 派生的所有内容也是 Wrap< /code> 应该可以通过这个找到。

The following determines whether something is a wrap:

template<class T>
struct is_Wrap { static const bool value = false; };

template<typename T> 
struct is_Wrap< Wrap<T> > { static const bool value = true; };

Since derivation is an Is-A relationship, everything derived from Wrap<T> also is a Wrap<T> and should be found by this.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文