Force compilation error on "0" argument (C++) - c++

Can anybody tell me if there is a way to force a compilation error when a const wchar_t* function argument gets passed a 0 pointer?
As example:
void func(const wchar_t* a)
{
...
}
int main()
{
...
func(0); // <- this should generate a compilation error
...
}
My intention here is not to skip any validation checks inside the function for this argument but rather prevent compilation if a function call simply makes no sense at all.
I am using Visual Studio 2019
Thanks!!
UPDATE
I tried to add an overload for std::nullptr_t as mentioned by #Jarod42
This generates a compilation error, but the error it produces is
"more than one instance of overloaded function matches the argument list"
although it prevents compilation, the error itself is kind of missleading and doesn't address the real problem
adding an overload with the parameter replaced by int type also get a missleading compilation error
"tried to acces a deleted function"
and yes, sadly none of those prevent a call with (const wchar_t*)0 argument
so, i would say that i want to reject the 0 literal as well as the (const wchar_t*)0argument

You might add overload for std::nullptr_t:
void func(std::nullptr_t) = delete;
Or maybe a catch all one:
template <typename T> void func(T) = delete;

Related

C++ overload resolution always resort to alias arg. over others as the arg. valid to all

How do we make (sure) C++ overload resolution will always resort to alias arg. than normal arg., so e.g. must pick
int func(string& s) {
// ...
}
over
int func(string s) { //...
}
when the argument valid to both?
thank you
If the argument is valid to both (eg std::string), then the code will not compile (GCC9.2) because of the ambiguity
error: call of overloaded 'func(std::string&)' is ambiguous
https://gcc.godbolt.org/z/qbvrAR
If you pass const char* or something else, which is default constructible to std::string, then the function, which takes copy of a string, will be called.
https://gcc.godbolt.org/z/DGSuEz
There is (not known to me) no way how to tell the compiler that he should prefer reference function over copy. You can check this snippet where I'm trying to explicitly call the reference, but compilation fails again due tu ambiguity:
https://gcc.godbolt.org/z/gZSdyj

function overloading with std::function and generic lambdas: std::string preferred over int

When trying to compiling this, suprisingly, it gives an error because the auto parameter of the lambda function has been resolved to std::string, and the compiler doesn't know how to convert std::string to int or Widget when calling test.
But, I wonder why the compiler has choosen the second invok function instead of the first one, when the first one would succeed:
#include <string>
#include <functional>
struct Widget {};
bool test(int );
bool test(Widget );
void invok(std::function<bool(int)> ); // #1
void invok(std::function<bool(std::string)> ); // #2
int main()
{
// error: unresolved overloaded function type
// invok(test);
// still error: no known conversion from std::string to
// int or Widget
invok([](auto&& x) {
return test(std::forward<decltype(x)>(x));
});
}
That example has been copied from a C++ proposal.
The compiler didn't choose #2. It's trying to decide if it can choose #2.
To do that, it asks "can this generic lambda be converted to std::function<bool(std::string)>"?
std::function's converting constructor says "only if it's callable with a std::string rvalue and the result type is convertible to bool".
Compiler tries that, deduce auto as std::string, substitute into the signature of the function call operator...success! Oops, the return type is auto, and it needs an actual type to answer the "is convertible" question. So it instantiates the body of the function call operator template to figure out the return type.
Ouch. The body isn't valid for std::string after all. Hard error and explosions follow.
Your overload remains ambiguous (sort of), but along the way to determining that your code runs into a hard error when trying out the two possibilities (passing an int or a string).
To see the ambiguity, add a ->bool to your lambda so it doesn't have to compile the body to determine the return value.
The body of a lambda is not in an area where a subsitution failure results in not an error. Instead you get a hard error there.
The easy fix is to make your lambda take an int explicitly.
If you want a generic solution:
#define RETURNS(...) \
noexcept(noexcept(__VA_ARGS__)) \
-> decltype(__VA_ARGS__) \
{ return __VA_ARGS__; }
#define OVERLOADS_OF(...) \
[](auto&&...args) \
RETURNS( __VA_ARGS__( decltype(args)(args)... ) )
and then
invok(OVERLOADS_OF(test));
does (at least closer to) the right thing.
This macro moves the failure from the body of the lambda, to a trailing return type. And the failure (that string cannot be passed to test) now occurs in a context where substitution failure causes not an error (SFINAE). So everything works.
The exact rules for what is SFINAE friendly and what is not require reading the standard. However, the rule of thumb is that works well is that compilers don't have to treat errors in bodies of functions as substitution errors, and that accessing the contents of an undefined class is a hard error. The first because it seemed a reasonable place to draw a line and make it easier for compiler writers; the second because the alternative is insanity or ODR bug bait.
In practice, the standards SFINAE rules are more arcane, and last I checked in C++14 there was an omission of SFINAE being required during template class partial specialization: every compiler supported it. But maybe I misread it. In any case, the rule of thumb I use seems just as useful as the standard text. Neither are going to be perfect.

C++ automatic constrctor call

Let's say we have got a raw C-style string "test". We can declare a function like this:
void printText(std::string textToPrint){
std::cout << textToPrint << "\n";
}
and we may call it in a following manner:
printText("test");
And this should be perfectly fine, as argument is an object, not a reference, so temporary object like std::string("test") should be created in time of calling function `printText()'.
Now given that, I have a following template:
template <typename T>
T checkMe(Proxy<T> arg){
std::cout << arg() << std::endl;
return arg();
}
where Proxy class declaration is as follows:
template <typename T>
class Proxy{
public:
Proxy(std::function<T&()> caller);
Proxy(std::shared_ptr<T> dataPtr);
T& operator()();
private:
std::function<T&()> m_functional;
std::shared_ptr<T> m_data;
};
It's purpose is to make some of the functions be called with two object types:
One is shared_ptr to the data and another is functional object, that returns this type of data.
Now when I want to call function checkMe error happens, that I do not know why appears and how to solve it. One thing is:
getMe(std::make_shared<int>(255));
And this in my opinion should be perfectly fine, as Proxy's constructor takes shared_ptr as argument and creates itself based on it. But this gives compiler's deduction error. Whereas, when I call function like this:
getMe<int>(std::make_shared<int>(255));
Well now it's fine. I do not know why does compiler cannot deduce the type on it's own.
Second case is calling it with a functional object:
getMe<int>(std::bind(getNumberMult,5,6));
Where getNumberMult is defined as follows:
int xy;
int& getNumberMult(int x, int y){
return xy = x*y;
}
Here conversion error occurs. Could someone please specify is it possible and how to achieve desired behavior of the given code and explain what is wrong with my understanding of the mechanism? I would like to use this code as follows:
getMe(std::make_shared<int>(300));
getMe(std::bind(getNumberMult, 6, 7));
Compiler errors:
when using
getMe<int>(std::bind(getNumberMult, 5, 6));
path/to/file:36: error: C2664: 'T getMe<int>(DataProxy<T>)' : cannot convert argument 1 from 'std::_Bind<true,int &,int &(__cdecl *const )(int,int),int,int>' to 'DataProxy<int>'
with
[
T=int
]
With T checkMe(Proxy<T> arg), arg should be a Proxy<T> (or inherit from it).
Compiler doesn't check the infinite possibilities to test each Proxy<T> can be construct from given argument.
So generally I know now why it is so, and what should I do to fix it.
Consider following object:
struct Test{
Test(std::string someString){}
};
So we need std::string just for constructing object of this class.
We can do without std::string created explicitly in following manner:
int main(){
Test someVariable("someRawString");
}
It's gonna work and it is completely fine. What happens underhood is:
compiler meets instruction for creating object of Test class
It sees, that given argument is not of type required by Constructor
because of the fact, that required argument is a value, not a reference (const reference would also be fine) it creates temporary object of type std::string and passes this temporary object to the constructor
Object is successfully created.
Now let's consider function:
void someTestFunction(Test someTest){}
It requires object of type Test, that is constructed from std::string
Given that, it should be fine to invoke this function in following manner:
someTestFunction("someRawText");
But it's not fine. This gives us error of converting arguments. Reason for it is quite simple: C++ allows only one step of converting, when passing parameters to the function. So compiler can:
cast raw string to std::string
create Test object with std::string
But it cannot:
cast raw string to std::string
cast std::string to Test (too many conversions)
invoke function with Test
Exactly the same things happened with the given code. To make it work we should use:
getMe<int>(std::make_shared<int>(300));
getMe<int>(std::function<int&()>(std::bind(getNumberMult, 6, 7)));
Why is it so?
std::make_shared<int> has return type of std::shared_ptr<int>, so no conversion was required to invoke a function.
std::bind... has a returning type different than std::function, it has it's own implementation defined return type. That is why this second cast would be required here, which is not allowed by C++. When we cast it explicitly, then only one implicit cast is required and everything works fine.

Conversion of template function pointer to bool fails

Consider the code:
void fnc(int, long, double*){}
template<int I> void f(int, long, double*){}
int main()
{
bool a = fnc; //(1) ok
bool b = f<4>; //(2) error
}
It triggers an error:
error: cannot resolve overloaded function 'f' based on conversion to type 'bool'
bool b = f<4> //(2) error
Why first case is correct, but second case isn't correct?
You are totally neglecting all the warnings, which are there to tell you that you're doing something very wrong.
Besides, you should use the & to get the function address.
Secondly, you're implicitly casting a function pointer to a bool variable.
Cast it explicitly to tell the compiler that you think you know what you're doing and you're sure about it:
bool b= (void*)&ff<4>;
I just have to say that casting stuff to avoid errors and warning is a bad idea.
In most cases the warnings and errors are there to help you avoid loss of data and things that usually do cause runtime errors.

Prevent silent cast from false to pointer

I have a function
void foo(int *bar)
{}
Visual Studio 2012 will now happily and without warnings compile if I call foo like this:
int main()
{
foo(false);
return 0;
}
If I however change foo(false) to foo(true) than I get an error:
1>main.cpp(132): error C2664: 'foo' : cannot convert parameter 1 from 'bool' to 'int *'
1> Conversion from integral type to pointer type requires reinterpret_cast, C-style cast or function-style cast
Any idea how I can make sure that I get an error when passing false, too? My only idea is to add a second private function "void foo(bool bar)". Then I indeed get the desired error stating that foo(bool bar) is private. But this only works when foo is called from outside the class and it clutters my interface.
First, as to why it accepts false but not true: The literal false will be interpreted as the integral 0 and a literal 0 will convert to a null pointer of any type. true on the other hand cannot be converted to a pointer type as it converts to an integral 1.
As to how to solve your problem: Your approach with an extra bool overload will work fine for both public and non-public callers as long as you don't implement the private overload. In that case public callers will get a compile error and member callers will get a linker error.
However, you may wish to consider additional things as well.
Does your function need to accept null pointers? If not, change it to accept by reference instead and the problem just goes away.
If your function really does need to accept null pointers then I would suggest in this case to just trust your users to call it correctly instead of cluttering your interface trying to prevent every possible misuse.
In C++11, you may write:
void foo(bool) = delete; // cannot be use by anybody (class itself included).
As vs2012 doesn't support = delete,
You may try this hack using SFINAE:
template <typename T>
typename std::enable_if<std::is_same<T, int>::value, void>::type
foo(T* t);
With the old C++98 way 'private without implementation':
private: // Fail to compile from outside
void foo(bool); // No implementation -> fail to link time if internally used.
You can wait for C++17, when Concepts can be used anywhere auto is in C++11, and write your signature as:
void foo( IsActually<int*>::template test x ) { }
... which actually looks pretty bad, but they may clean up the syntax by then.