29

Consider the following code:

void foo(bool parameter) {
    std::cout << parameter << "\n";
}

int main() {
    foo("const char *argument");
}

I want the compiler to raise a warning when passing const char* instead of bool as a parameter to function foo.

But GCC implicitly converts it. I tried -Wall, -Wextra, and -Wpedantic, but none of these issue a warning. Is there a flag that could catch such an implicit conversion (invalid parameter type)?

Ignore the fact that the function has an argument of type bool, which some may see as bad code style. I can't refactor that part.

The standard just mentions such an implicit conversion will occur:

A prvalue of integral, floating-point, unscoped enumeration, pointer, and pointer-to-member types can be converted to a prvalue of type bool.

I know such behavior is very convenient in if (ptr) statements, but for me, in the case of passing parameters, it is clearly wrong and a source of bugs.

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
  • 10
    ...and good for bad surprises: If there is a function which accepts `std::string` and another which accepts `bool` instead, guess which one is chosen for `"const char *argument"`. (Spoiler alert: yes the second - and it drove me crazy until I got a clue.) ;-) – Scheff's Cat Feb 04 '19 at 12:12
  • 2
    a bit offtopic, but I am puzzled why you think having a `bool` parameter would be bad coding-style.. – 463035818_is_not_an_ai Feb 04 '19 at 12:16
  • 1
    @user463035818 "Uncle Bob said so" could be a good reason. He argues that function with `bool` parameter never has a single responsibility. Uncle Bob has many strong opinions about coding though. – Yksisarvinen Feb 04 '19 at 12:23
  • @Yksisarvinen you mean that there should be a `fooTrue` and a `fooFalse` instead? Hum, maybe i could agree in some cases, but not in general, though if Bob said so there must be some truth to it – 463035818_is_not_an_ai Feb 04 '19 at 12:26
  • You may have another overload `void foo(const char *parameter)`. – frogatto Feb 04 '19 at 12:32
  • @user463035818 yes, I was referring to suggestion made by Uncle Bob. – Szymon Zimnowoda Feb 04 '19 at 12:34
  • 1
    Implicit conversions are one of the biggest mistakes in the C++ language. The implicit integer conversions are probably one of the largest general sources of bugs, outside of pointers. This is an excellent question, and kudos to you for thinking about how to design interfaces that *prevent* bugs in your code. – Cody Gray - on strike Feb 05 '19 at 03:47
  • suggest, when compiling, to include the option `-Wconversion` – user3629249 Feb 05 '19 at 20:32

2 Answers2

29

You could declare an overload of foo for pointers as deleted:

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

Or better yet, as @Ted comments, simply declare a vanilla overload to not compile any implicit conversions:

template <class T>
void foo(T) = delete;
Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108
Paul Evans
  • 27,315
  • 3
  • 37
  • 54
  • 2
    Not wrong but in a real world example these are probably (multiple) functions (maybe even from other files/sources) and that could make this seem quite exhausting. – Stack Danny Feb 04 '19 at 12:23
  • 4
    Starting from C++11, you shoul actually declare it as `deleted`… this will generate earlier and more meaningful error messages. Alternatively, declare it with a body that raises a `static_assert` if `T` is not `bool` (template is ill-formed if it always raises a `static_assert`, that's the only reason for this check). – Arne Vogel Feb 04 '19 at 12:27
  • 4
    ... or just `void foo(T) = delete;` to delete all implicit conversions. – Ted Lyngmo Feb 04 '19 at 13:28
17

I want the compiler to raise a warning when passing const char* instead of bool as a parameter to function foo. ... I tried -Wall, -Wextra, and -Wpedantic

You need to add -Wconversion to your compiler flags. Note that seems to work with clang (recent or older version), but not with gcc.

If this triggers too many warnings that you don't want to handle, you can selectively enable -Wstring-conversion (clang only).

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
lubgr
  • 37,368
  • 3
  • 66
  • 117
  • 1
    I tried but without luck: [**Live Demo on coliru**](http://coliru.stacked-crooked.com/a/aed36ef8557e9af4). Did I oversee something? – Scheff's Cat Feb 04 '19 at 12:15
  • 1
    @Scheff Weird, it seems to be handled differently in `clang` and `gcc`. Updated the answer accordingly. – lubgr Feb 04 '19 at 12:18
  • 1
    I just found this [The new Wconversion option](https://gcc.gnu.org/wiki/NewWconversion#The_new_Wconversion_option) and in fact the implicit conversion from `const char*` to `bool` isn't mentioned at all. Looks like it isn't covered in gcc... – Scheff's Cat Feb 04 '19 at 12:20
  • @Scheff fwiw also [no error/warning for uniform initialization of a bool with a `const char*`](http://coliru.stacked-crooked.com/a/f8800b65e6f5e880) – 463035818_is_not_an_ai Feb 04 '19 at 12:22