This question already has answers here:
Overload resolution with std::function
(2 answers)
Closed 6 years ago.
consider some code:
void foo() { }
bool bar() { return true; }
struct S
{
void operator=(std::function<void()> f){f();};
void operator=(std::function<bool()> f){f();};
};
int main() {
S s;
s = foo; // ok
s = bar; // error: use of overloaded operator '=' is ambiguous
}
How can I make this example unambiguous?
The problem you're running into is that std::function<void(Args...)> is allowed to discard return types - so both std::function<void()> and std::function<bool()> can be constructed from a bool(*)(). The latter will forward through the return from bar, but the former will just discard it. That's perfectly valid behavior, but causes this to be ambiguous.
What you probably want is to avoid std::function altogether:
template <class F>
void operator=(F f) { f(); }
Related
This question already has answers here:
Why do I have to access template base class members through the this pointer?
(3 answers)
ISO C++ Standard - rules regarding examining dependent base. Why?
(1 answer)
Closed 8 months ago.
This code doesn't compile:
#include<iostream>
using namespace std;
template<class T>struct Base {
void f(int) { cout << "Base::f() int\n"; }
};
template<class T>struct Derived:Base<T> {
void g(int i) { f(i); } // should be this->f(i) to pass compile
};
int main(){
Derived<char> obj;
obj.g(1); // cfunction short
return 0;
}
I googled and search on stackoverflow, it says that in the error-line, I should use write either
void g(int i) { this->f(i); }
or
void g(int i) { Base<T>::f(i); }
Yes, they work. I tried none-template version, doesn't need this complex qualifier. As long as both f() and g() doesn't use any template type parameter, I didn't think of a rule on template deduction upon these 2 functions.
Is this some hidden rule behind template resolution that I should add extra qualifier, and why my original code fail to compile?
This question already has answers here:
What's a use case for overloading member functions on reference qualifiers?
(4 answers)
Closed 10 months ago.
I just discovered this is valid C++:
struct S {
int f() &; // !
int g() const &; // !!
};
int main() {
S s;
s.f();
s.g();
}
IIUC, this is passed to f by reference and to g be passed by const-reference.
How was this useful to anyone?
They are useful for both providing safety and optimizations.
For member functions returning a pointer to something they own (either directly or via view types like std::string_view or std::span), disabling the rvalue overloads can prevent errors:
struct foo {
int* take_ptr_bad() { return &x; }
int* take_ptr() & { return &x; }
int x;
};
foo get_foo();
void bar() {
auto ptr = get_foo().take_ptr_bad();
// ptr is dangling
auto ptr = get_foo().take_ptr();
// does not compile
}
The other is to provide some optimizations. For instance, you might overload a getter function to return an rvalue reference if this is an rvalue to prevent unnecessary copies:
struct foo {
const std::string& get_str() const & {
return s;
}
std::string&& get_str() && {
return std::move(s);
}
std::string s;
};
void sink(std::string);
foo get_foo();
void bar() {
sink(get_foo().get_str());
// moves the string only if the r-value overload is provided.
// otherwise a copy has to be made, even though the foo object
// and transitively the string is temporary.
}
These are how I use the feature, and I'm sure there are more use cases.
This question already has answers here:
Is there any way in C++ to refer to a function template while neither calling it nor supplying its template parameters?
(4 answers)
Convert template function to generic lambda
(2 answers)
How do I make a functor out of an arbitrary function?
(2 answers)
Closed 2 years ago.
I have a function returning a std::pair, which I want to use to call an overloaded member function. I am not aware of any way to unpack a tuple in-place (which I'd prefer), so std::apply is my best bet, I think.
This works with a combination of tuple_cat and forward_as_tuple when the member function is not overloaded, but otherwise, the compiler complains about an unresolved overload.
That is understandable, given that std::apply just takes a function pointer, but I'd still like to know whether it can be made to work in a readable way.
Here's some example code:
#include <iostream>
#include <tuple>
#include <utility>
std::pair<int, int> func() { return { 0, 1 }; }
class MyClass {
public:
int memFun(int);
int memFun(int, int);
};
int MyClass::memFun(int i){ return 2*i; }
int MyClass::memFun(int a, int b){ return a+b; }
int main(){
MyClass myClass;
/* works */
std::pair pair { func() };
int number { myClass.memFun( pair.first, pair.second ) };
/* doesn't work (unresolved overload) */
int number { std::apply(
&MyClass::memFun,
std::tuple_cat( std::forward_as_tuple(myClass), func() )
) };
std::cout << number << "\n";
return 0;
}
Is there an elegant (=readable) way to do this without a temporary?
I only found this question and so far don't think it fully applies.
This question already has answers here:
How to call through a member function pointer?
(2 answers)
Closed 4 years ago.
I try to give a reference to a member function (func) to a function (Multiprotocol) and call it with an object (z) of this class.
But i have problems with the line
result = z.*f(std::forward<Args>(args)...));
I tried things like
z.(*f) (std::forward<Args>(args)...))
and
z.(*(&f)(std::forward<Args>(args)...));
But i don't knwow how to this. Can anybody help me?
class test
{
public:
static int func()
{
std::cout << "in func";
}
};
class MultiProtocol
{
public:
template<typename Function, typename... Args>
bool functionImpl(Function f, Args&&... args)
{
int result = 0;
result = z.*f(std::forward<Args>(args)...));
return result;
}
private:
test z;
};
Main is:
int main()
{
MultiProtocol rr;
rr.functionImpl(&test::func);
}
Nearly, it is:
(z.*f)(std::forward<Args>(args)...)
Cannot be
z.(*f) (std::forward<Args>(args)...))
z.(*(&f)(std::forward<Args>(args)...));
as we should use operator .* (or ->*).
z.*f(std::forward<Args>(args)...) would be valid if f(args...) would return int test::* (pointer on member) as it is actually z .* (f(std::forward<Args>(args)...)).
This question already has answers here:
Functions with const arguments and Overloading
(3 answers)
Closed 6 years ago.
Why does const create a different signature when its applied to a struct pointer as opposed to a struct?
E.g.
typedef struct test_s {
int foo;
} test;
void foo(test *ptr){
return;
}
// This is ok
void foo(const test *ptr){
return;
}
void foo(test t){
return;
}
//This is an error
void foo(const test t){
return;
}
(tested on gcc version 4.9.2)
To be more specific, why is it that the bottom one is an error when the pair with the pointers is not an error. The referenced duplicate question (Functions with const arguments and Overloading) would also seem to argue that the case with the pointers should be duplicates.
void foo(const test t){
return;
}
is an error since it is the same as:
void foo(test t){
return;
}
which makes it a duplicate of the previous function.
When the argument to a function is test*, you can dereference the pointer and modify it. The modification will be visible in the calling function.
void foo(test *ptr){
ptr->foo = 10; // The state of the object in the calling function
// is changed.
return;
}
When the argument to a function is const test*, you can dereference the pointer to access it but not modify it.
void foo(const test *ptr){
std::cout << ptr->foo << std::endl; // OK
ptr->foo = 10; // Not OK
return;
}
For the same reason, you can overload:
void foo(test& t);
void foo(const test& t);
When you try to overload
void foo(test t);
void foo(const test t);
Both are equally good candidates when you call it. The compiler cannot disambiguate between the two. In addition, take a look at one of the answers to the dupe. It cites the section of the C++ standard that states why the last two are equivalent.