g++ - how do I disable implicit conversion from 0 to pointer types?

心不动则不痛 提交于 2020-05-15 06:15:32

问题


Specifically, I want the following code to fail:

void a(void*){}
int main(){
    a(0); // FAIL
    a(NULL); // FAIL
    a(nullptr); // success
}

And I want the following code to compile:

void a(int){}
void a(void*){}
int main(){
    a(0); // calls first a
    a(NULL); // calls first a; that's why I have -Werror
    a(nullptr); // calls second a
}

The following code does not compile currently, but should according to my rule:

void a(std::size_t){}
void a(void*){}
int main(){
    a(0); // two candidates
}

Any idea how to make g++ behave like that?


回答1:


This may not be perfect, but if you trully want to have overloads with int and pointer, you could use some helper class like this:

#include <iostream>
#include <iomanip>
using std::cout;
using std::endl;

template<typename T = void> class ptr {
    T* it;
public:
    ptr(T* it = nullptr): it(it) {}
    ptr(const ptr<T>&) = default;
    ptr& operator = (const ptr<T>&) = default;
    operator T* () { return it; }
    T& operator * () { return *it; }
    T* operator -> () { return it; }
    ptr& operator += (int x) { it += x; return *this; }
    ptr& operator -= (int x) { it -= x; return *this; }
    ptr& operator ++ () { ++it; return *this; }
//  etc...
public:
    template<typename P>
      ptr(P* it): it(it) {}
    template<typename P>
      ptr(ptr<P> it): it((T*)it) {}
};
template<> class ptr<void> {
    void* it;
public:
    ptr(void* it = nullptr): it(it) {}
    ptr(const ptr<void>&) = default;
    ptr& operator = (const ptr<void>&) = default;
    operator void* () { return it; }
public:
    template<typename P>
      ptr(P* it): it(it) {}
    template<typename P>
      ptr(ptr<P> it): it((void*)it) {}
};

void a(std::size_t x) {
    cout << "first: " << x << endl; }
void a(ptr<const int> p) {
    cout << "second: " << (p ? *p : -1) << endl; }
void a(ptr<int> p, ptr<> q) {
    cout << "third: " << (p ? *p : -1) << ", "
        << (q ? "some" : "null") << endl;
    a(p); }
int main(){
    a(0);           // first: 0
    a(NULL);        // first: 0 but warning [-Wconversion-null]
    a(new int(3), nullptr); // third: 3, null + second: 3
}

It is not finished (maybe remove that explicit, add more operators, special conversion from nullptr_t, etc), just and idea.

EDIT: Few changes in code, template constructors and conversion to ptr<const int> test.




回答2:


You can compile with -Wzero-as-null-pointer-constant to get a warning when you use 0 or NULL instead of nullptr. To promote that to an error, I believe using -Werror=zero-as-null-pointer-constant would work.

Unfortunately, this is simply a warning and is not able to change overload resolution rules. I also believe NULL must be defined as 0 rather than nullptr in order for the warning to catch it, but at least as of GCC 4.9, std::is_null_pointer<decltype(NULL)>::value is false and GCC warns when using NULL.




回答3:


Given that NULL is either identical to 0 or nullptr, I don't think you can force a C++ compiler to behave the way you describe it. I could imagine using clang's AST interface to detect the cases exactly the way you describe. I'd expect that typical C++ code will contain a number of intentional uses of 0 and/or NULL to mean pointers and/or integers as appropriate.




回答4:


Here is a relatively simple solution to the first problem (it requires C++11):

struct must_be_void_ptr{
    must_be_void_ptr(void* p) : p(p) {}
    must_be_void_ptr(int) = delete; // Disallow implicit conversion from 0
    void* p;
    operator void*() { return p; }
};

void a(must_be_void_ptr p){
    void* vp = p;
}

int main(){
    a(nullptr);
    a(0);
}



回答5:


Use:

gsl::not_null

From Guideline Support Library. I highly recommend GSL. It's created and backed by many C++ experts, Bjarne Stroustrup himself and Herb Sutter among them. And the C++ Core Guidelines are actively being integrated into the compiler warnings and static analyzers.



来源:https://stackoverflow.com/questions/25462821/g-how-do-i-disable-implicit-conversion-from-0-to-pointer-types

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!