Reputation: 543
I found error in my code that I think should be marked with warning. Compiled with /W4 but it don't show any warning (only about unreferenced formal parameter).
#include <cstdio>
void A(int item, unsigned int count, unsigned team_count)
{
printf("A, count, team count\n");
}
void A(int item, unsigned int count=1, bool is_team=true)
{
printf("A, count, is_team\n");
return A(item, count, is_team ? count : 0);
}
int main()
{
A(0, false); // <- bool to unsigned int
return 0;
}
Here bool is casted to unsigned int. Is there any way to detect that? Tried Cppcheck but it don't find this.
Upvotes: 0
Views: 67
Reputation: 27528
A very safe way to prevent such things is to wrap your count types in classes without implementing automatic conversions.
class Count
{
private:
int m_count;
public:
explicit Count(int count) : m_count(count)
{
assert(m_count >= 0);
}
int Get() const { return m_count; }
};
class TeamCount
{
private:
int m_count;
public:
explicit TeamCount(int count) : m_count(count)
{
assert(m_count >= 0);
}
int Get() const { return m_count; }
};
// ...
void A(int item, Count count, TeamCount team_count);
void A(int item, Count count = Count(1), bool is_team = true);
// ...
A(0, false); // <- compiler error
A(0, TeamCount(0), false); // <- compiler error
A(0, Count(0), false); // OK
You can do a similar thing with your other primitive type parameters.
Upvotes: 0
Reputation: 310990
Here is an example how you can achieve what you want
#include <iostream>
void f( int ) { std::cout << "f( int )" << std::endl; }
void f( bool ) = delete;
int main()
{
f( true );
return 0;
}
Compiler error
prog.cpp:8:10: error: use of deleted function ‘void f(bool)’
f( true );
^
Applied to your code the example will look like
#include <iostream>
void A( int item, unsigned int count, unsigned team_count )
{
std::cout << "A, count, team count" << std::endl;
}
void A( int item, unsigned int count = 1, bool is_team = true )
{
std::cout << "A, count, is_team" << std::endl;
return A( item, count, is_team ? count : 0 );
}
void A( int, bool ) = delete;
int main()
{
A( 0, false );
return 0;
}
Error:
prog.cpp:18:14: error: use of deleted function ‘void A(int, bool)’
A( 0, false );
^
Upvotes: 2
Reputation: 43662
The standard says this is acceptable §4.7/p4 Integral Conversions:
If the source type is bool, the value false is converted to zero and the value true is converted to one.
Regarding how to detect this (since it's not an error) and depending on your use-case, you could either do some clang-tooling yourself or write a wrapper with some template deduction magic on the lines of:
#include <cstdio>
#include <type_traits>
template<typename T, typename U>
void A(int item, T, U) {
static_assert(!std::is_same<T, unsigned int>::value ||
(!std::is_same<U, unsigned int>::value &&
!std::is_same<U, bool>::value),
"Something was wrong");
}
template<>
void A(int item, unsigned int count, unsigned int team_count)
{
printf("A, count, team count\n");
}
template<unsigned int count = 1, bool is_team = true>
void A(int item, unsigned int, bool)
{
printf("A, count, is_team\n");
return A(item, count, is_team ? count : 0);
}
int main()
{
// A(0, false); - not acceptable
// A(0, 22); - not acceptable
A(0, static_cast<unsigned int>(2), false);
A(0, static_cast<unsigned int>(33), static_cast<unsigned int>(45));
return 0;
}
Note that the base template deduction mechanism doesn't require C++11, although some functions used above do.
Upvotes: 1