免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 4212 | 回复: 13
打印 上一主题 下一主题

今天又學到一招 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-08-01 16:30 |只看该作者 |倒序浏览
原來is_pod是用這個搞定的.
namespace __gnu_internal
{
  typedef char __one;
  typedef char __two[2];

&nbsp;&nbsp;template<typename _Tp>
&nbsp;&nbsp;__one __test_type(int _Tp::*);
&nbsp;&nbsp;template<typename _Tp>
&nbsp;&nbsp;__two& __test_type(...);
} // namespace __gnu_internal




class A {};

int main () {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout << sizeof(__gnu_internal::__test_type<int>(0)) << endl;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout << sizeof(__gnu_internal::__test_type<A>(0)) << endl;
}

论坛徽章:
0
2 [报告]
发表于 2009-08-01 21:42 |只看该作者

论坛徽章:
0
3 [报告]
发表于 2009-08-01 22:59 |只看该作者
没看懂LZ的意思

论坛徽章:
0
4 [报告]
发表于 2009-08-01 23:28 |只看该作者
谁用谁知道

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
5 [报告]
发表于 2009-08-02 02:05 |只看该作者
原帖由 dtimes6 于 2009-8-1 16:30 发表
原來is_pod是用這個搞定的.
namespace __gnu_internal
{
  typedef char __one;
  typedef char __two[2];

  template<typename _Tp>
  __one __test_type(int _Tp::*);
  template<typename _Tp>
  __two& __test_type(...);
} // namespace __gnu_internal




class A {};

int main () {
     cout << sizeof(__gnu_internal::__test_type<int>(0)) << endl;
     cout << sizeof(__gnu_internal::__test_type<A>(0)) << endl;
}


这是 is_buildin 。

论坛徽章:
0
6 [报告]
发表于 2009-08-02 03:42 |只看该作者
没有什么,只是用来测试,类型A是不是一个类.

我也写过一个类似的,用来检测一个类型是不是一个类的基类。
#include <iostream>
using namespace std;

template<class T, class U>
class IsBaseClass {
    typedef char ONE;
    typedef struct { char dummy[2];} TWO;
    static ONE test1(U); // Testing can T be converted to U.

    static TWO test1(...);
    enum { IsConvert = sizeof( test1(T()) ) == sizeof(ONE) };

    static ONE test2(int T::* );  //  testing is T a class type.

    static TWO test2(...);
    enum { IsClass = sizeof( test2(0) ) == sizeof(ONE) };
public:
    enum { YES = IsConvert && IsClass };
};

#define IsBase(T, U) IsBaseClass<T, U>::YES

class Base{};
class Derived : public Base {int a_;};
class T{};

nt main (int argc, char *argv[]) {
    cout << IsBase(Derived, Base) <<"\n";
    return 0;
}i


[ 本帖最后由 apple753357 于 2009-8-2 03:49 编辑 ]

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
7 [报告]
发表于 2009-08-02 13:31 |只看该作者

回复 #6 apple753357 的帖子

原帖由 apple753357 于 2009-8-2 03:42 发表
#include <iostream>
using namespace std;

template<class T, class U>
class IsBaseClass {
    typedef char ONE;
    typedef struct { char dummy[2];} TWO;
    static ONE test1(U); // Testing can T be converted to U.

    static TWO test1(...);
    enum { IsConvert = sizeof( test1(T()) ) == sizeof(ONE) };

    static ONE test2(int T::* );  //  testing is T a class type.

    static TWO test2(...);
    enum { IsClass = sizeof( test2(0) ) == sizeof(ONE) };
public:
    enum { YES = IsConvert && IsClass };
};

#define IsBase(T, U) IsBaseClass<T, U>::YES

class Base{};
class Derived : public Base {int a_;};
class T{};

int main (int argc, char *argv[]) {
    cout << IsBase(Derived, Base) <<"\n";
    return 0;
}



1. static ONE test1(U); // Testing can T be converted to U.

struct A {};
struct B { B(A) {} };
struct C { operator A() const { return A(); }  };

IsBase(A, B)
B不是内建类型, A能隐式转换到B, 但显然A不是B的子类。

IsBase(C, A)
A不是内建类型, C能隐式转换到B, 但显然C不是A的子类。


2. test1(T())

T不一定有无参数的构造函数。即使有,也不一定可访问。

论坛徽章:
0
8 [报告]
发表于 2009-08-02 22:48 |只看该作者

回复 #7 OwnWaterloo 的帖子

请问针对这两种情况你有什么好的解决方法吗?
因为一般我写代码的时候很少用隐式转换,要用的话也是写一个函数来完成转换,所以真没考虑到这种情况。

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
9 [报告]
发表于 2009-08-02 23:43 |只看该作者

回复 #8 apple753357 的帖子

《modern c++ design》中, SFINAE只用于一般转换性检测。

《mcd》中检测D是否是B的子类使用的条件是,是否存在D的"指针"到B的"指针"的隐式转换 ……
而不是直接检测是否存在D到B的隐式转换。

多了这一条, 就可以避免上面的A、B、C的误判。
并且:
/*non-explicit*/ B::B(A* );
C:: operator A*() const;

也是不行的, 因为它们定义的分别是A* -> B, C->A*的隐式转换, 而不是A* -> B*, C* -> A*


因为检测的是指针的转换性, 所以还要加上B!=void的判定。
任何对象指针都可以隐式转换为(const/volatile) void*指针, 但void不是任何类型的父类。

当然, 依然检测不出非公有继承的情况……


第2个问题也是《MCD》提出过, 书里用了一个很ws的办法……
T makeT();
sizeof( test( makeT() ) );

这样,test 都会根据makeT 的返回类型选择一个合适重载。
sizeof 再检测选中的test重载的返回类型的大小。

与test类似, makeT也不需要有定义…… 所以无论T的构造函数是怎样的, 都不会造成影响。

[ 本帖最后由 OwnWaterloo 于 2009-8-2 23:53 编辑 ]

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
10 [报告]
发表于 2009-08-02 23:51 |只看该作者

回复 #9 OwnWaterloo 的帖子

对第1个问题, 好像使用引用更好一点?  因为不存在void& ,  可以少判定一个条件。

好像也不是……

虽然, 这样的代码可能不会被直接写出来:
IS_SUPER_SUB(B&,D&); //  这会造成reference to reference, 在当前C++中是错误。

却可能会在范型编程时, 类型参数被上层逻辑添加上&。



对第2个问题……   好像也还有其他的ws解决方式……

1. 需要访问构造函数的
sizeof( test( T() ) );


2. 《mcd》
T makeT();
sizeof( test( makeT() ) );


3. 使用指针
T* pt;
sizeof( test( *pt ) );
sizeof( test( *static_cast<T*>(0) ) );


4. 或者引用
T& rt;
sizeof( test( rt ) );

[ 本帖最后由 OwnWaterloo 于 2009-8-3 00:00 编辑 ]
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP