Selecting ambiguous constructor manually - c++

When a call to a function (member class function or free function) is ambiguous, we can select it easily using static_cast<> to the function type we calling:
struct S {
void f(uint32_t, uint8_t) {
std::cout << "1\n";
}
void f(uint32_t, uint32_t) {
std::cout << "2\n";
}
};
int main() {
S s;
auto f1 = static_cast<void(S::*)(uint32_t, uint8_t)>(&S::f);
(s.*f1)(1,1);
auto f2 = static_cast<void(S::*)(uint32_t, uint32_t)>(&S::f);
(s.*f2)(1,1);
}
But I wonder if it is possible to do something similar for constructors. For example, in the following structure:
struct S {
S(uint32_t, uint8_t) {
std::cout << "1\n";
}
S(uint32_t, uint32_t) {
std::cout << "2\n";
}
};
Is it possible to manually solve ambiguous constructor call for creating S s(1,1);?

Is this what you had in mind?
S s1(static_cast<uint32_t>(1), static_cast<uint32_t>(2));
S s2(static_cast<uint32_t>(1), static_cast<uint8_t>(2));
This disambiguates the constructor-calls by specifying the types explicitly in the arguments.

Why don't just cast to the correct type? 1 is an int literal so it makes some "confusion" when passing to unsigned parameters
int main() {
S s;
s.f(1, (uint8_t)1);
s.f(1, (uint32_t)1);
s.f(1, 1U);
}
Demo on Godlbolt

Related

Error in vector of struct with implemented Functions

I get the Erro:
"no instance of constructor "std::vector<_Ty, _Alloc>::vector
[with _Ty=FunctionToUpdate, _Alloc=std::allocator<FunctionToUpdate>]" matches the argument list"
No matter how I change it, it persists, as long I keep it as a class. If I keep it all in just a simple .cpp without class and header, it all resolves easily.
My.h:
#include <vector>
#include <functional>
#include <iostream>
struct Params
{
std::vector<int> Integers;
std::vector<std::string> Strings;
};
struct FunctionToUpdate
{
int Version;
std::function<void(int, Params)> Function;
Params Parameters;
};
class Error
{
public:
Error();
void testFunctionA(int a, Params p);
void testFunctionB(int a, Params p);
protected:
const static std::vector<FunctionToUpdate> table;
};
Here is my .cpp, please assist me, I can't find the error:
#include "ErrorHandling.h"
Error::Error()
{
for (auto functionToUpdate : table)
{
functionToUpdate.Function(functionToUpdate.Version, functionToUpdate.Parameters);
std::cout << "############################################" << std::endl;
}
std::cout << "Done!" << std::endl;
}
void Error::testFunctionA(int a, Params parameter)
{
//std::cout << "Size Integers: " << parameter.Integers.size() << std::endl;
//std::cout << "Size Strings: " << parameter.Strings.size() << std::endl;
std::cout << a << std::endl;
for (auto& integer : parameter.Integers)
{
std::cout << integer << std::endl;
}
for (auto& integer : parameter.Strings)
{
std::cout << integer << std::endl;
}
}
void Error::testFunctionB(int a, Params parameter)
{
std::cout << a << std::endl;
std::cout << parameter.Integers.at(0) << std::endl;
}
const std::vector<FunctionToUpdate> Error::table
{ // <-- here the Error happens
{ 100, &testFunctionA, { {177}}},
{ 1948, &testFunctionB, { {314}}},
};
int main()
{
Error error;
}
Your code has a few issues
First, the correct initialization of static member Error::table would be as follows:
const std::vector<FunctionToUpdate> Error::table
{
{ 100, &Error::testFunctionA, { { {177} }, { {"string"} } }},
{ 1948, &Error::testFunctionB, { { {314} }, { {"string"} } } }
};
Note that the syntax &Error::testFunctionA for addressing the member function pointer. Additionally, the Params has two vectors. One is std::vector<int> and the other is std::vector<std::string>. In your code, the std::vector<std::string> has not been mentioned.
In FunctionToUpdate the member function pointer type is wrong. Using typed member function pointer, you could
// forward declaration
class Error;
// member function pointer type
using ErrorFunType = void(Error::*)(int, Params);
struct FunctionToUpdate
{
int Version;
ErrorFunType Function;
Params Parameters;
};
Secondly, the call to pointer to the member function in Error::Error() is wrong. It needs an (Error class) instance to call with. For example:
for (auto functionToUpdate : table)
{
(this->*functionToUpdate.Function)(
functionToUpdate.Version, functionToUpdate.Parameters
);
// or more generic `std::invoke` (since c++17)
// std::invoke(functionToUpdate.Function
// , this, functionToUpdate.Version
// , functionToUpdate.Parameters);
// ...
}
The above changes will make, your code compiles again!
In case of wondering, how to handle the pointer to member function with std::function, (one way) to wrap the instance to call the member along with the std::function type.
Following is the example:
// forward declaration
class Error;
// member function pointer
using ErrorFunType = std::function<void(Error*, int, Params)>;
struct FunctionToUpdate
{
int Version;
ErrorFunType Function;
Params Parameters;
};
now in Error::Error()
Error::Error()
{
for (auto functionToUpdate : table)
{
functionToUpdate.Function(this
, functionToUpdate.Version, functionToUpdate.Parameters);
}
}
See a demo

Did std::bind implement std::ref and std::cref to disambiguate the function call?

I know that I shouldn't overload a function for just parameters differ only in one of them passed by copy and the other by reference:
void foo(int x)
{
cout << "in foo(int x) x: " << x << endl;
}
void foo(int& x)
{
cout << "in foo(int& x) x: " << x << endl;
}
int main()
{
int a = 1;
foo(5); // ok as long as there is one best match foo(int)
foo(a); // error: two best candidates so the call is ambiguous
//foo(std::move(a));
//foo(std::ref(an)); // why also this doesn't work?
}
So a code that uses std::bind can be like this:
std::ostream& printVec(std::ostream& out, const std::vector<int> v)
{
for (auto i : v)
out << i << ", ";
return out;
}
int main()
{
//auto func = std::bind(std::cout, std::placeholders::_1); // error: stream objects cannot be passed by value
auto func = std::bind(std::ref(std::cout), std::placeholders::_1); // ok.
}
So std::ref here to ensure passing by reference rather than by value to avoid ambiguity?
* The thing that matters me: Does std::bind() implemented some wrapper to overcome this issue?
Why I can't use std::ref in my example to help the compiler in function matching?
Now that you know passing by value and reference are ambiguous when overload resolution tries to compare them for choosing a best viable function, let's answer how would you use std::ref (or std::cref) to differentiate between pass-by-value and pass-by-reference.
It turns out to be ... pretty simple. Just write the overloads such that one accepts a int, and the other accepts a std::reference_wrapper<int>:
#include <functional>
#include <iostream>
void foo(int x) {
std::cout << "Passed by value.\n";
}
void foo(std::reference_wrapper<int> x) {
std::cout << "Passed by reference.\n";
int& ref_x = x;
ref_x = 42;
/* Do whatever you want with ref_x. */
}
int main() {
int x = 0;
foo(x);
foo(std::ref(x));
std::cout << x << "\n";
return 0;
}
Output:
Passed by value.
Passed by reference.
42
The function pass the argument by value by default. If you want to pass by reference, use std::ref explicitly.
Now let's answer your second question: how does std::bind deal with this type of scenario. Here is a simple demo I have created:
#include <functional>
#include <type_traits>
#include <iostream>
template <typename T>
struct Storage {
T data;
};
template <typename T>
struct unwrap_reference {
using type = T;
};
template <typename T>
struct unwrap_reference<std::reference_wrapper<T>> {
using type = std::add_lvalue_reference_t<T>;
};
template <typename T>
using transform_to_storage_type = Storage<typename unwrap_reference<std::decay_t<T>>::type>;
template <typename T>
auto make_storage(T&& obj) -> transform_to_storage_type<T> {
return transform_to_storage_type<T> { std::forward<T>(obj) };
}
int main() {
int a = 0, b = 0, c = 0;
auto storage_a = make_storage(a);
auto storage_b = make_storage(std::ref(b));
auto storage_c = make_storage(std::cref(c));
storage_a.data = 42;
storage_b.data = 42;
// storage_c.data = 42; // Compile error: Cannot modify const.
// 0 42 0
std::cout << a << " " << b << " " << c << "\n";
return 0;
}
It is not std::bind, but the method used is similar (it's also similar to std::make_tuple, which has the same semantic). make_storage by default copies the parameter, unless you explicitly use std::ref.
As you can see, std::ref is not magic. You need to do something extra for it to work, which in our case is to first decay the type (all references are removed in this process), and then check whether the final type is a reference_wrapper or not; if it is, unwrap it.

Converting a lambda to function pointer typedef

I have a 3rd party API that has a function that takes a function pointer as an argument (sample types):
// defined in "Api.h"
typedef int (*Callback) (int x);
unsigned char ApiCall(int p, Callback cb);
int ApiCall(int p, Callback cb) {
return cb(p);
}
And I'm trying interact with this API using a class instance method; here's a sample class:
class ApiWrapper {
public:
int ApiCallback(int x) { return this->factor_ * x; }
static int WorkingApiCallback(int x) { return 3 * x; }
ApiWrapper(int f) { this->factor_ = f; }
private:
int factor_;
}
And a main function to test:
#include <iostream>
#include <functional>
int main() {
ApiWrapper a(2);
using std::placeholders::_1;
std::function<int(int)> lambda = std::bind( &ApiWrapper::ApiCallback, a, _1 );
std::cout << "Class: " << a.ApiCallback(21) << std::endl;
std::cout << "Lambda: " << lambda(21) << std::endl;
std::cout << "Static ApiCall:" << ApiCall(21, ApiWrapper::WorkingApiCallback) << std::endl;
// NOT WORKING
std::cout << "Static ApiCall:" << ApiCall(21, lambda) << std::endl;
std::cout << "Static ApiCall:" << ApiCall(21, this.ApiCallback) << std::endl;
return 0;
}
Is there a way to achieve this without using the static member; as I need to associate/use state each time the callback is invoked by the 3rd party lib.
Online Runnable Source: https://ideone.com/7nVSi8
Thanks!
You are going to have to somehow associate a non-member with the function pointer, as it does not take any sort of context argument. You are going to have a non-member function at some point, no way around that. And that function cannot be a capturing lambda.
One option is to have a (possibly thread local) global pointer that holds the instance.
i.e. you do:
myType * glbInst;
..void someFunc()
{
myType myInst;
glbInst = &myInst;
apiCall([] (int) glbInst->member(x); });
}
Another option is to use libffi's closure system to create a function at run-time and have the instance be part of the saved data. I use this pattern very often but it's a bit complicated to paste here.
Is there a way to achieve this without using the static member;
There's a hackish solution.
Define a non-member function.
Store a pointer to an object that can be accessed by the non-member function.
Call the member function of the object from the non-member function.
ApiWrapper* objectForCallback = NULL;
int NonMemberFunction(int x)
{
assert(objectForCallback != NULL);
return objectForCallback->ApiCallback(x);
}
and the setup for the above to work:
ApiWrapper a(2);
objectForCallback = &a;
Now you can use:
std::cout << "Static ApiCall:" << ApiCall(21, NonMemberFunction) << std::endl;

Is it possible to use member function call as default argument?

Here is my code:
struct S
{
int f() { return 1; }
int g(int arg = f()) { return arg; }
};
int main()
{
S s;
return s.g();
}
This fails to compile with the error:
error: cannot call member function 'int S::f()' without object
Trying this->f() doesn't work either, as this may not be used in that context.
Is there a way to make this work, still using the default argument?
Of course it can be worked around by not using default arguments at all:
int g(int arg) { return arg; }
int g() { return g(f()); }
however that gets verbose considering that in the "real code" there are more parameters before arg, and several functions following this pattern. (And even more ugly if there were multiple default arguments in the one function).
NB. This question looks similar at first, but in fact he is asking how to form a closure, which is a different problem (and the linked solution doesn't apply to my situation).
You can only use members there if they are static. From a C++11 draft standard (n3299), §8.3.6/9:
Similarly, a non-static member shall not be used in a default argument, even if it is not evaluated, unless it appears as the id-expression of a class member access expression (5.2.5) or unless it is
used to form a pointer to member (5.3.1).
E.g., this works:
struct S {
static int f() { return 1; }
int g(int arg = f()) { return arg; }
};
int main()
{
S s;
return s.g();
}
This also works (I think that's what the first expression means):
struct S {
int f() { return 42; }
int g(int arg);
};
static S global;
int S::g(int arg = global.f()) { return arg; }
int main()
{
S s;
return s.g();
}
As for this, it is indeed not allowed (§8.3.6/8):
The keyword this shall not be used in a default argument of a member function.
The default arguments page on cppreference.com has a lot of details regarding the subject—it can get quite complex.
If you are allowed to use experimental features from C++17, you can use std::optional from the STL (see here for further details).
In other terms something like:
int g(std::optional<int> oarg = std::optional<int>{}) {
int arg = oarg ? *oarg : f();
// go further
}
EDIT
As suggested in the comments, the code above should be logically equivalent to the one below:
int g(std::optional<int> oarg = std::optional<int>{}) {
int arg = oarg.value_or(f());
// go further
}
This one is a bit more readable (isn't it?), but please note that it executes f in any case.
If that function is expensive, maybe it doesn't worth it.
I add another answer, that is completely different from the previous one and could solve your issue.
The idea is to use another class and the right mix of explicit and non-explicit constructors.
It follows a minimal, working example:
#include <functional>
#include <iostream>
template<class C, int(C::*M)()>
struct Arg {
std::function<int(C*)> fn;
Arg(int i): fn{[i](C*){ return i; }} { }
explicit Arg(): fn{[](C* c){ return (c->*M)(); }} { }
};
struct S {
int f() { return 1; }
int h() { return 2; }
void g(int arg0,
Arg<S, &S::f> arg1 = Arg<S, &S::f>{},
Arg<S, &S::h> arg2 = Arg<S, &S::h>{})
{
std::cout << "arguments" << std::endl;
std::cout << "arg0: " << arg0 << std::endl;
std::cout << "arg1: " << arg1.fn(this) << std::endl;
std::cout << "arg2: " << arg2.fn(this) << std::endl;
}
};
int main() {
S s{};
s.g(42, 41, 40);
s.g(0);
}
The example shows how you can mix both default parameters and non defaulted ones.
It's quite simple to modify it and let g be a function having an empty argument list, as in the original question.
I'm also quite sure that one can refine the example and end with something better than that, anyway it should be a good point from which to start.
It follows the solution applied to the original example from the question:
#include <functional>
template<class C, int(C::*M)()>
struct Arg {
std::function<int(C*)> fn;
Arg(int i): fn{[i](C*){ return i; }} { }
explicit Arg(): fn{[](C* c){ return (c->*M)(); }} { }
};
struct S {
int f() { return 1; }
int g(Arg<S, &S::f> arg = Arg<S, &S::f>{}) {
return arg.fn(this);
}
};
int main() {
S s{};
return s.g();
}
And that's all, it's possible to do that, even without static methods or global variables.
Of course, we can use our this somehow. It's a matter of bending the language a bit...

Passing a member name as argument

I am trying to pass a member of class as argument to a function (not member method). The simple example of my intention would be like this.
template <typename ObjType>
void myOutput(ObjType* obj, ????)
{
std::cout << obj->???? << std::endl;
}
struct A
{
int a;
};
struct B
{
std::string b;
};
int main()
{
A A1;
B B1;
A1.a = 1;
B1.b = "something";
myOutput(&A1, A1::a);
myOutput(&B1, B1::b);
return 0;
}
So my question is what should i replace "????" with? I am not using C++11.
Thanks.
EDIT:
To clarify my intentions. The function myOutput doesn't really know the name of my member, and i do not want to use a function like memberToString() or something.
So the output should look like this for first call.
void myOutput(A* obj, ????)
{
std::cout << obj->a << std::endl;
}
and for the second
void myOutput(B* obj, ????)
{
std::cout << obj->b << std::endl;
}
If you know the member name at compile time, you can use a member pointer to refer to the member.
template <typename ObjType, typename MembType>
void myOutput(ObjType* obj, MembType memb)
{
std::cout << obj->*memb << std::endl;
}
This can then be called as such:
myOutput(&A1, &A::a);
myOutput(&B1, &B::b);
Naturally, you should ask yourself why it is you want to do this, and if it wouldn't be possible to simply pass A1->a or B1->b directly into the function as a single argument, instead.