如何检查类型是否为int的typedef

时间:2011-12-13 08:28:12

标签: c++ constructor c-preprocessor typedef

在C ++中,我希望有一个类,其构造函数如下:

class A {
  explicit A(A* other) { ... }
  explicit A(intptr_t other) { ... }
};

问题在于用户是否使用

进行初始化
A a(0);

然后,在64位系统上,编译器会抱怨它不知道0是否应转换为A*intptr_t,这是公平的。由于我希望这个简单的符号起作用,我添加了以下构造函数:

explicit A(int a) { assert(a==0); ... }

断言是因为这是唯一有意义的整数。现在,问题出现在32位系统中,其中intptr_t实际上是...... int!所以现在,系统抱怨有两个构造函数采用相同的参数类型(这也是公平的)。

所以我的问题是:预处理器是否有办法检测intptr_t实际上是int,在这种情况下,不能用int编译构造函数。或者,是否有另一种方法可以使A a(0)符号无效,而无需使用int添加构造函数,但不删除两个第一个构造函数中的任何一个(并且不会使它们隐式)。

5 个答案:

答案 0 :(得分:3)

这样的东西
#if INTPTR_MAX == INT_MAX

可能会做到这一点,但它仍然会导致long和{{}} int大小相同,ptrint_tlong的typedef。 另一种可能性(但不知道你是否可以使用它) 将使用uintptr_t,而不是intptr_t

除此之外:预处理器不知道类型,所以问题 在那里无法解决。你将不得不使用某种元编程 技巧:使用,使int构造函数成为模板 boost::enable_if仅在参数类型为int时激活它。 如果ptrint_tint,则激活的函数永远不会 使用过,因为它永远不会比非模板更好 具有相同签名的功能。如果ptrint_t不是int,那么。{ 当参数具有类型时,模板实例化将是更好的匹配 int。 (请注意,我自己从未尝试过这种方式:听起来像我这样 应该是可能的,但我对boost::enable_if并不熟悉 一定要。)

答案 1 :(得分:1)

为什么不简单地实现一个无参数的构造函数,就好像other 0一样?如果由于某种原因你不想,我建议使用类型特征,前提是你可以访问C ++ 11编译器或者提升:

class A { 
public:
    explicit A(A* other) { ... } 
    explicit A(intptr_t other) { ... } 

    template <class T>
    explicit A(T other)
    {
        static_assert(std::is_convertible<T, intptr_t>::value, "Could not convert value to intptr_t");
        static_assert(std::is_integral<T>::value, "Argument must be integral");
        intptr_t p = other;
        ...
    }
}; 

您可以摆脱静态断言和类型检查,但是当您执行以下操作时,您将收到警告(取决于您的警告级别,甚至可能会变成错误)而不是编译器错误:

A a(0.0f);

答案 2 :(得分:0)

我认为最简单的方法是声明所有6个构造函数(int,long,long long和它们的无符号变体),而不是使用intptr_t。

答案 3 :(得分:-1)

  

还有另一种方法可以使A a(0)符号有效

只需介绍一个template构造函数。

class A {
public:
  template<typename T>
  explicit  A (T t) { assert(t==0); }  // explicit matters ?

  explicit A(A* other) { ... }
  explicit A(intptr_t other) { ... }
};

这将解决您的32位和64位问题!

答案 4 :(得分:-1)

您还可以传递一个参数,该参数决定调用哪个参数:

struct TakePtr{};
struct TakeInt{};

class A {
  A(A* other, const TakePtr&) { ... }
  A(intptr_t other, const TakeInt&) { ... }
};

这样你可以确定调用哪个构造函数:

A a2( 0, TakeInt() );     // calls the 2nd constructor, taking int
A a1( &a2, TakePtr() );   // calls the 1st constructor, taking a pointer