Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

enforcing type safety when casting char* to bool in C++11

Following code compiles fine without any warnings (with default options to g++). Is there a flag that we can use to ask g++ to emit warnings in such cases?

void foo(bool v) {
}

void bar() {
  foo("test");
}
like image 352
user3612009 Avatar asked Sep 22 '15 10:09

user3612009


2 Answers

I like to try clang -Weverything and pick the warnings that pop out:

void foo(bool) {}

void bar() {
  foo("test");
}

void baz() {
    foo(nullptr);    
}

int main() {}

main.cpp:5:7: warning: implicit conversion turns string literal into bool: 'const char [5]' to 'bool' [-Wstring-conversion] foo("test");

main.cpp:8:9: warning: implicit conversion of nullptr constant to 'bool' [-Wnull-conversion] foo(nullptr);

Unfortunately, neither -Wstring-conversion nor -Wnull-conversion is supported by g++. You could try and submit feature request / bug report to gcc.

like image 126
TemplateRex Avatar answered Oct 22 '22 10:10

TemplateRex


If I really wanted to prevent such a function being passed a pointer, I would do this in C++11;

 void foo(bool);
 template<class T> void foo(T *) = delete;

 void bar()
 {
     foo("Hello");
 }

which will trigger a compiler error.

Before C++11 (not everyone can update for various reasons) a technique is;

 void foo(bool);
 template<class T> void foo(T *);   // note no definition

 void bar()
 {
     foo("Hello");
 }

and then have the definition of foo(bool) somewhere (in one and only one compilation unit within your build). For most toolchains that use a traditional compiler and linker (which is most toolchains in practice, including most installations of g++) the linker error is caused by foo<char const>(char const*) not being defined. The precise wording of the error is linker dependent.

Note that the errors can be deliberately circumvented by a developer. But such techniques will stop accidental usage.

If you want to allow any pointer except a char const * being passed, simply declare void foo(const char *) as above and don't declare the template.

like image 41
Peter Avatar answered Oct 22 '22 11:10

Peter