Stopping function implicit conversion - c++

I came across a strange situation today where I needed a function to not implicitly convert values.
After some looking on google I found this http://www.devx.com/cplus/10MinuteSolution/37078/1954
But I thought it was a bit stupid to use a function overload for every other type I want to block so instead I did this.
void function(int& ints_only_please){}
int main()
{
char a=0;
int b=0;
function(a);
function(b);
}
I showed the code to a friend and he suggested I added const before int so the variable isn't editable, however when I did started compiling fine but it shouldn't, look below to see what I mean
void function(const int& ints_only_please){}
int main()
{
char a=0;
int b=0;
function(a); //Compiler should stop here but it doesn't with const int
function(b);
}
Does anyone know why this is?

Use templates to get the desired effect:
template <class T>
void foo(const T& t);
template <>
void foo<int>(const int& t)
{
}
int main(){
foo(9); // will compile
foo(9.0); // will not compile
return 0;
}
Note that we only write a special version of the template for int so that a call that has any other type as a template parameter will result in a compile error.

It is legal to bind a temporary to a const reference, but not a non-const reference.
A char can be implicitly converted to an int and the temporary that is the result of this conversion can be bound to a const int& function parameter extending the temporary's lifetime until the function exits.

Related

When there are two methods with the same name in the class and same parameter, the compiler looks at one over another?

I am new to C++ and this might sound very basic. The compiler always looks at the method that returns a const pixel value for me, which I do not want it to bc I want to change the value of the returned pixel. This situation does not happen during my previous assignments but it happens this time. Is there any way to resolve this? Thank you so much.
provided PNG class:
const HSLAPixel & getPixel(unsigned int x, unsigned int y) const;
HSLAPixel & getPixel(unsigned int x, unsigned int y);
my code:
HSLAPixel & original = png_.getPixel((*it).x, (*it).y);
They aren't quite the same. One is declared const. The other one is non-const. The compiler will use the const version when your PNG is marked const and the non-const version otherwise.
I did this:
#include <iostream>
class Foo {
public:
void foo(int i) const { std::cout << "Const version.\n"; }
void foo(int i) { std::cout << "Non-const version.\n"; }
void myFunction() const { foo(10); }
};
int main() {
Foo foo;
foo.foo(10);
foo.myFunction();
}
When I run it, the first call to foo() prints the Non-const message, and the second one prints the const message.

How to declare reference to lambda in C++ [duplicate]

This question already has answers here:
Is auto as a parameter in a regular function a GCC 4.9 extension?
(2 answers)
Closed 5 years ago.
I want to declare a function that takes as argument a function (or lambda) with a specific prototype.
The first try is:
#include <iostream>
using namespace std;
int test(int (&val)(int)) {
return val(2);
}
int main() {
cout << test([](int v){
return v+100;
});
return 0;
}
witch results in error: invalid initialization of non-const reference of type 'int (&)(int)' from an rvalue of type 'main()::<lambda(int)>'
I tried to add const specified to the type but I don't know where exactly so I tried the following that works with GCC (-std=c++14), however I suspect it is illegal since it fails with clang:
int test(const auto& val) {
return val(2);
}
I know I can use template or function pointers or std::function to achieve the same, then please consider this a didactic question. I want to know what does GCC deduce the type of val to, in the second example above (int test(const auto& val)).
template <typename F>
int test(F val) {
return val(2);
}
int test(int val(int)) {
return val(2);
}
int test(std::function<int(int)> val) {
return val(2);
}
I want to declare a function that takes as argument a function (or lambda) with a specific prototype.
Closures generated by lambda expression have a unique and anonymous type. They could also be generic (i.e. template operator()). There is no "easy" way of declaring a function accepting lambdas with a specific prototype. Your best bet is either using a constrained template parameter with something like std::is_invocable or using some sort of type erasure like function_view.
Note: if your lambda is captureless it is implicitly convertible to a function pointer. E.g.
int test(int (*)(int)) { }
test([](int) -> int {}); // OK
test([i = 0](int) -> int {}); // compile-time error
I want to know what does GCC deduce the type of val to, in the second example.
int test(int val(int))
...is equivalent to...
int test(int (*val)(int))
In fact, having both of them in the same scope results in a redefinition error:
int test(int val(int)) {
return val(2);
}
int test(int (*val)(int)) {
return val(2);
}
prog.cc:5:5: error: redefinition of 'test'
int test(int (*val)(int)) {
^
prog.cc:1:5: note: previous definition is here
int test(int val(int)) {
^

It is possible to overload function by const specifier?

whether it is possible to overload function by const specifier. That is, we have two functions, one constant the other is not, can we say that the constant function overloaded non-const function ?
Yes and No.
It depends on where you put the const specifier.
When defining member functions, this is possible (Yes-part):
int f() { /*code*/ } //invoke this function on non-const object
int f() const { /*code*/ } //ok : invoke this function on const object
Note that in the absence of the first function, even non-const object will invoke the second function (i.e const member function) and in the absence of the second function, you wouldn't be able to invoke the first function on const objects!
But this is not possible (No-part):
int g() { /*code*/ }
const int g() { /*code*/ } //error: redefinition
irrespective of whether they're member functions or free functions.
Per ยง 13.1 / 2:
It's not possible to put const in return-type to overload:
Function declarations that differ only in the return type cannot be
overloaded.
int func();
const int func(); // Error
It's not possible to put const in parameter-list to overload:
Parameter declarations that differ only in the presence or absence of
const and/or volatile are equivalent.
void func(int x);
void func(const int x); // Error
BUT, it's possible:
const and volatile type-specifiers buried within a parameter type
specification are significant and can be used to distinguish
overloaded function declarations.
void func(int &x);
void func(const int &x); // OK
And, it's possible to put const at end of method declaration to distinguish overloads:
int func();
int func() const; // OK

Is the compiler allowed to select const ref over ref during overload resolution?

Some background:
I came across something the other day that got me thinking about overload resolution in nested function calls. Consider the code below:
#include <iostream>
void printer(const int &a)
{
std::cout << a << "\n";
}
const int& func(const int &a)
{
std::cout << "const int& ";
return a;
}
int& func(int &a)
{
std::cout << "int& ";
return a;
}
int main()
{
int a = 42;
const int b = 21;
printer(func(a));
printer(func(b));
return 0;
}
This code prints
int& 42
const int& 21
So, obviously func(a) sees that a is a non-const int. The compiler must also see that the printer function wants a const int& argument. And there exists a func(...) that returns a const int&. I looked into the C++ standard and it says that const refs and refs are considered distinct parameter types (and that is why it picks the int& for func(a)).
To the question:
Is the compiler allowed to use the func(const int &) version instead of the func(int&) when calling func(a)?
(Perhaps there is some kind of optimization possibility if it sees that the result is passed to a function wanting a const int& parameter.)
Overload resolution does not consider the return type. That is, it will only look at the argument to the function and the different overloads, disregarding how the returned value is going to be used.
For a more explicit test, consider changing the non-const overload to:
void func( int& ) {}
which will fail to compile, even if there is a different similar overload that would allow the code to compile.

Determining if being passed a temporary

Lets say I have a class C, and a function make_c(x) which creates instances of C.
C stores x by reference.
How can I write make_c(x) to give a compile error when x is an unnamed temporary (that would of course destruct at the end of line, leaving a dangling reference) but accept named temporaries and other values?
I believe this should have the semantics you're looking for:
template<typename X>
C make_c(X&& x)
{
static_assert(
!std::is_rvalue_reference<decltype(std::forward<X>(x))>::value,
"x must not be a temporary"
);
return C(std::forward<X>(x));
}
Caveat: this won't work as-is with VC++ 2010 due to deficiencies in its implementation of decltype (you'd need to wrap decltype in std::identity<>).
I don't think it's possible within the language, because you'd need to check the flow control through arbitrary functions.
struct Foo{
};
Foo const & sanitize(Foo const & f){ return f;}
void checkThisFunction(Foo const & f){
//we'd like to ensure at compile time that f is not a temporary
}
int main(){
Foo f;
checkThisFunction(sanitize(f));
checkThisFunction(sanitize(Foo()));
return 0;
}
Unless I'm completely misunderstanding rvalue references, this sort of thing should be doable with simple overloading.
void foo(int&&) = delete;
void foo(const int&) { }
int main()
{
int a;
foo(a);
foo(42); //error, prefers binding to the deleted overload
}