I attempted today's leetcode challenge in C++. You have to find cousins in a binary tree. Here's my code.
template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
class Solution {
public:
bool isCousins(TreeNode* root, int x, int y) {
this->x = x;
this->y = y;
return visit(overloaded{
[](const bool& r) {
return r;
},
[](const optional<int>& r) {
return false;
}
}, helper(root));
}
private:
int x;
int y;
variant<const bool, optional<int>> helper(TreeNode* node) {
if (node == nullptr) {
return variant<const bool, optional<int>>((optional<int>()));
}
else if (node->val == x) {
return variant<const bool, optional<int>>(optional<int>(0));
}
else if (node->val == y) {
return variant<const bool, optional<int>>(optional<int>(0));
}
else {
auto l = helper(node -> left);
auto r = helper(node -> right);
return visit(overloaded{
[](const bool& l, optional<int>& r) {
assert(!r.has_value());
return variant<const bool, optional<int>>(l);
},
[](optional<int>& l, const bool& r) {
assert(!l.has_value());
return variant<const bool, optional<int>>(r);
},
[](optional<int> l, optional<int> r) {
if (l.has_value() && r.has_value()) {
return variant<const bool, optional<int>>(*l > 0 && *l == *r);
}
else if (l.has_value()) {
++*l;
return variant<const bool, optional<int>>(l);
}
else if (r.has_value()) {
++*r;
return variant<const bool, optional<int>>(r);
}
else {
return variant<const bool, optional<int>>((optional<int>()));
}
}
}, l, r);
}
}
};
A testcase that demonstrates my issue is
[1,3,2,null,null,7,4,null,null,5,6,null,8,null,9]
8
9
The code above runs and completes successfully. However, if I remove a single const keyword in line 10 ([](bool& r) {) then it returns a different (incorrect) answer. const is for compile-time safety, so shouldn't affect semantics, but I guess something strange is happening with const overloading? What's going on exactly?
Possibly related: it also breaks my mental model that if, instead of declaring l, rin lines 34,35, I pass them directly as arguments to visit (ie. return visit(overloaded{..}, helper(node->left), helper(node->right)), it also fails. I would again expect that to have no effect on semantics.
Removing the const in this case changes the meaning of the code, by changing which function is selected in overload resolution.
Consider the following overload set and call:
void f(int const &) { std::cout << "i"; }
void f(bool) { std::cout << "b"; }
int main()
{
int const i = 42;
f(i); // prints i
f(42); // prints i
}
both call the first function (as expected), because a int const & binds to a int const, as well as int&& (a temporary int).
However, if we remove the const in the first function of the overload set, and make the same call:
void f(int &) { std::cout << "i"; }
void f(bool) { std::cout << "b"; }
int main()
{
int const i = 42;
f(i); // prints b
f(42); // prints b
}
the first function is not selected, because an int &, cannot bind to a int const. However, a bool can bind to an int const, (after an implicit conversion), and it calls the second function. Similarly, an int & cannot bind to a int&&, but a bool can, so it calls the second function.
This same reasoning applies to your example, but I've removed the variant, and custom overload set, as it simplifies the situation, without changing the underlying problem.
Related
Given a number of overloaded functions taking differently-typed parameters, is there a way to get the return type or one of the parameter types for a particular overload, within a templated context, at compile time? Consider for example this situation where the overloaded function takes a parameter reference as an out-value:
struct struct_a { };
struct struct_b { };
struct struct_c { };
float process(struct_a) { return 5.0f; }
bool process(struct_b) { return true; }
int process(struct_c) { return -1; }
void process_in_place(struct_a, float& out) { out = 5.0f; }
void process_in_place(struct_b, bool& out) { out = true; }
void process_in_place(struct_c, int& out) { out = -1; }
template<typename T>
void do_process(T val)
{
auto result1 = process(val);
std::cout << result1 << std::endl;
// ???
//using post_process_type = std::invoke_result_t<decltype(process)&(std::declval<T>)>;
// ???
post_process_type result2;
process_in_place(val, result2);
}
int main()
{
do_process(struct_a());
do_process(struct_b());
do_process(struct_c());
}
How would I know what type the out-param should be prior to invoking whichever version of process_in_place is ultimately selected?
using post_process_type = decltype(process(std::declval<T>()));
This will do. decltype will just look at the return type after overload resolution selects the right process.
Considering the following toy example, where I declare a class which encapsulates ublas from boost libraries:
#include <boost/numeric/ublas/matrix_sparse.hpp>
#include <iostream>
namespace ublas = boost::numeric::ublas;
class UblasEncapsulated {
public:
ublas::compressed_matrix<float>::reference operator()(int i, int j){
std::cout << "Non const reference" << std::endl;
MtrUpdated_ = true;
return mtr_(i, j);
}
ublas::compressed_matrix<float>::const_reference operator()(
int i, int j) const {
std::cout << "Const reference" << std::endl;
return mtr_(i, j);
}
UblasEncapsulated() { MtrUpdated = false; }
private:
ublas::compressed_matrix<float> mtr_(3, 3);
bool MtrUpdated_;
};
int main() {
UblasEncapsulated foo;
foo(2, 0) = 1.0f;
float const foo_float = foo(2, 0);
return 0;
}
I was expecting the output
Non constant reference
Constant reference
But I got
Non constant reference
Non constant reference
What am I doing wrong? How can I properly track when mtr_ could have its values changed?
foo is non-const, so the non-const version of foo.operator() will be called. It doesn't matter how the value it returns is used.
If you really want to know that MtrUpdated_ is only set true if an element is actually assigned to, you will need to use a proxy class:
class UblasEncapsulated {
public:
class proxy {
public:
proxy(UblasEncapsulated* ptr, int i, int j)
: ptr_(ptr), i_(i), j_(j)
{}
proxy& operator=(float f) {
ptr_->MtrUpdated_ = true;
ptr_->mtr_(i_, j_) = f;
return *this;
}
operator float() {
return ptr_->mtr_(i_, j_);
}
private:
UblasEncapsulated* ptr_;
int i_;
int j_;
};
proxy operator()(int i, int j) {
return proxy(this, i, j);
}
ublas::compressed_matrix<float>::const_reference operator() (int i, int j) const {
return mtr_(i, j);
}
UblasEncapsulated()
: mtr_(3, 3),
MtrUpdated_(false)
{}
private:
ublas::compressed_matrix<float> mtr_;
bool MtrUpdated_;
};
Live Demo
Note that you should avoid using a proxy class if you can get away with it since it doesn't play nicely with things like auto or template argument deduction.
I am looking through the CMBC source code and came across this code snippet:
void goto_symext::operator()(const goto_functionst &goto_functions)
{
goto_functionst::function_mapt::const_iterator it=
goto_functions.function_map.find(goto_functionst::entry_point());
if(it==goto_functions.function_map.end())
throw "the program has no entry point";
const goto_programt &body=it->second.body;
operator()(goto_functions, body);
}
I have never seen a operator()(args) syntax before and googling does not seem to yield anything.
As answered in the comments, /*return type*/ operator()(/*params*/) is the syntax for overloading the () operator.
struct Foo { void operator()() { std::cout << "Hello, world!"; } };
Foo f;
f(); //Hello, world!
That would be the function call operator, which allows you to make function-like objects.
struct Functor {
bool operator()(int a, int b = 3);
};
bool Functor::operator()(int a, int b /* = 3 */) {
if ((a > (2 * b)) || (b > (2 * a))) {
return true;
} else {
return false;
}
}
// ...
Functor f;
bool b = f(5); // Calls f.operator()(5, 3).
bool c = f(3, 5);
It has the benefits that you can save state information in the function-like object's fields, and that if necessary, you can hide overloaded versions of the operator within the object instead of leaving them exposed.
class Functor {
int compareTo;
public:
Functor(int cT);
bool operator()(int a);
bool operator()(char c);
};
Functor::Functor(int cT) : compareTo(cT) { }
bool Functor::operator()(int a) {
if ((a > (2 * compareTo)) || (compareTo > (2 * a))) {
return true;
} else {
return false;
}
}
bool Functor::operator()(char c) { return false; }
It can be used to make it easier to write code that can accept any function instead of depending on function pointers. [It works especially well when used in tandem with templates, in this regard.]
See here or here for more information.
I would like to have some fair idea how to map functions with variable arguments,return type of int and call it by a string..
Just for an example...
int func1(int a, int b);
int func2(int a1, int b1 , int* c1);
int func3(char* dummy);
int func4(double x, long y, int z, char** table);
int func5(double d1, double b1);
int func6(int* p, double* q, int i);
I just need a common function called
int CallFunction("funcname", param1, param2, ...);
for example
CallFunction("func1", 10, 20); /* calling function func1 and return func1 result*/
I know how to map functions using functions pointers having constant arguments but variable arguments seems to be complicated.. could anyone shower some idea how to do it.
I even explored Variadic templates.. But seems to complicated calling functions using strings..
I had exact the same problem.
Solved it with this solution:
#include <iostream>
#include <map>
#include <string>
int func0(int x)
{
std::cout << x << std::endl;
}
int func1(int x, int y)
{
std::cout << (x + y) << std::endl;
}
template <class... Args>
struct MapHolder{
static std::map<std::string, int (*)(Args...)> CallbackMap;
};
template <class... Args>
std::map<std::string, int (*)(Args...)> MapHolder<Args...>::CallbackMap;
class Callback {
public:
template <class ...Args>
void RegisterFunction(std::string name, int (*func)(Args...)) {
MapHolder<Args...>::CallbackMap[name] = func;
}
template <class ...Args>
int ExecuteFunction(std::string name, Args &&... args) {
return MapHolder<Args...>::CallbackMap[name](std::forward<Args>(args)...);
};
};
int main(int argc, char *argv[])
{
Callback cb;
cb.RegisterFunction("func0", &func0);
cb.RegisterFunction("func1", &func1);
cb.ExecuteFunction("func0", 42);
cb.ExecuteFunction("func1", 42, 42);
return 0;
}
This snippet is based on this answer. I only use other class/function names.
I'm not sure if this is what you're looking for, but anyway...
1. Creating a generic value holder
boost.any didn't make it into the standard, and, in case you don't know what it is, it allows you to store any C++ value in a single type (any) and get it back if you know the type. The following is a toy implementation of it:
struct TypeHandler {
void* (*copyFrom)(void *src);
void (*destroy)(void *p);
};
template<typename T>
TypeHandler *thandler() {
struct THandler {
static void *copyFrom(void *p) { return new T(*(T *)p); }
static void destroy(void *p) { delete (T *)p; }
};
static TypeHandler th = { &THandler::copyFrom, &THandler::destroy };
return &th;
}
TypeHandler contains two pointer to functions that know how to copy and how to destroy a specific C++ type. A Value can hold any type because it's composed of a void * and a pointer to a TypeHandler. When copying or destroying is required on the instance it asks to the specific type handler function...
struct Value {
TypeHandler *th;
void *p;
Value(const Value& other) : th(other.th), p(th->copyFrom(other.p)) { }
template<typename T> Value(const T& x) : th(thandler<T>()), p(new T(x)) { }
~Value() { th->destroy(p); }
Value& operator=(const Value& other) {
if (this != &other) {
th->destroy(p);
th = other.th;
p = th->copyFrom(other.p);
}
return *this;
}
template<typename T>
Value& operator=(const T& other) {
th->destroy(p);
th = thandler<T>();
p = new T(other);
return *this;
}
template<typename T>
T& to() const {
if (th != thandler<T>()) throw Error("type mismatch");
return *(T*)p;
}
};
Note that Value is copyable and can be passed by value and can be returned by functions.
Any copyable object is implicitly convertible into a Value and I can also convert it back to the original type with to<T>().
2. Creating the name->function maps
std::map<std::string, Value (*)(const Value&)> map1;
std::map<std::string, Value (*)(const Value&, const Value&)> map2;
Value call(const std::string& name, const Value& x1) {
return map1.at(name)(x1);
}
Value call(const std::string& name, const Value& x1, const Value& x2) {
return map2.at(name)(x1, x2);
}
Here I've created explicit maps for 1 and 2 arguments. May be this can be done using C++11 variadic templates, I didn't try. In C++03 libraries it's common to see this kind of stuff copy-n-pasted up to say n=20 to cover reasonable cases.
3. Macrology
To simplify registration of functions I wrote two ugly macros. May be this can be done also using variadic macros or templates (I'm not so sure about it, especially the automatic registration of the wrapper in the map).
#define regfunc1(name, t1) \
Value name(const Value& x1) { \
return name(x1.to<t1>()); \
} \
struct name##_ { \
name##_() { map1[#name]=&name; } \
} name##_instance
#define regfunc2(name, t1, t2) \
Value name(const Value& x1, const Value& x2) { \
return name(x1.to<t1>(), x2.to<t2>()); \
} \
struct name##_ { \
name##_() { map2[#name]=&name; } \
} name##_instance
4. Use
double square(double x) {
return x*x;
}
double hyp2(double x, double y) {
return x*x+y*y;
}
int mylen(const std::string& s) {
return s.size();
}
regfunc1(square, double);
regfunc2(hyp2, double, double);
regfunc1(mylen, std::string);
int main() {
Value x = 42;
Value y = std::string("This is a test");
Value z = 3.14;
printf("%0.3f\n", call("square", z).to<double>());
printf("%0.3f\n", call("hyp2", z, z).to<double>());
printf("mylen(\"%s\") = %i\n",
y.to<std::string>().c_str(),
call("mylen", y).to<int>());
return 0;
}
I have a question about equality comparison of lambdas.
I've tried to read some references but I've found nothing about this.
[] (Args ...args) -> ReturnType { ... };
For this type of lambdas, which are not closures actually because they have empty capture list, operators == and != works in the same way as for static functions (well, it seems, compiler generates them as static functions as well). But for closures any attempt to compare in the same way causes compilation error.
Here is simple programm for example:
#include <typeinfo>
#include <iostream>
struct WrapperBase {
virtual ~WrapperBase() = default;
virtual bool operator==(WrapperBase& v) = 0;
virtual bool operator!=(WrapperBase& v) = 0;
};
template<typename _Tp>
struct Wrapper : WrapperBase {
Wrapper(const _Tp& v) : value(v) { }
bool operator==(WrapperBase& v) override {
try {
Wrapper<_Tp>& vv = dynamic_cast<Wrapper<_Tp>&>(v);
return value == vv.value;
}
catch(std::bad_cast& err) { }
return false;
}
bool operator!=(WrapperBase& v) override {
try {
Wrapper<_Tp>& vv = dynamic_cast<Wrapper<_Tp>&>(v);
return value != vv.value;
}
catch(std::bad_cast& err) { }
return true;
}
//
_Tp value;
};
template<typename _Tp>
WrapperBase* create_wrapper(const _Tp& v) {
return new Wrapper<_Tp>(v);
}
struct Base {
Base(int a, int b) : wrapper(nullptr), a(a), b(b) { }
virtual ~Base() { delete wrapper; }
virtual WrapperBase* create_wrapper() = 0;
WrapperBase* wrapper;
int a;
int b;
};
struct ClassA : Base {
ClassA(int a, int b) : Base(a, b) {
wrapper = create_wrapper();
}
WrapperBase* create_wrapper() override {
auto lambda = [] (int v1, int v2) { return v1 + v2; };
return ::create_wrapper(lambda);
}
};
struct ClassB : Base {
ClassB(int a, int b) : Base(a, b) {
wrapper = create_wrapper();
}
WrapperBase* create_wrapper() override {
auto lambda = [=] (int v1, int v2) { return a + b + v1 + v2; };
return ::create_wrapper(lambda);
}
};
int main(int argc, char** argv) {
std::cout << std::boolalpha;
// all works fine:
ClassA a1(1, 2);
ClassA a2(3, 4);
std::cout << (*a1.wrapper == *a1.wrapper) << std::endl; // true
std::cout << (*a2.wrapper == *a2.wrapper) << std::endl; // true
std::cout << (*a1.wrapper == *a2.wrapper) << std::endl; // true
// cause compilation error:
ClassB b1(1, 2);
ClassB b2(3, 4);
std::cout << (*b1.wrapper == *b1.wrapper) << std::endl;
std::cout << (*b2.wrapper == *b2.wrapper) << std::endl;
std::cout << (*b1.wrapper == *b2.wrapper) << std::endl;
return 0;
}
Comparing lambdas created in instances of ClassA always return true even if they are created in different context (just as I said). On the other hand, ClassB do not even compile because operator == and != for its lambda is not found.
It seems, this programm is not well-formed, and comparing of lambdas in the way I've tried causes undefined behavior of the programm. But if it's really undefined behavior, how can they be compared? (I guess, nohow)
For this type of lambdas, which are not closures actually because they
have empty capture list, operators == and != works in the same way as
for static functions (well, it seems, compiler generates them as
static functions as well).
It works because the closure type of a lambda without captures provides a conversion operator that returns a function pointer. Those are comparable. [expr.prim.lambda]/6 (emphasis mine):
The closure type for a lambda-expression with no lambda-capture
has a public non-virtual non-explicit const conversion function to
pointer to function having the same parameter and return types as the
closure type’s function call operator. The value returned by this
conversion function shall be the address of a function that, when
invoked, has the same effect as invoking the closure type’s function
call operator.
(If the conversion operator was explicit the comparison would not work)
Roughly, a lambda of the form [] {} translates to
struct closure_type
{
private:
static void call() {}
public:
// closure_type() = delete; // Commented for the sake of the demo
closure_type& operator=(closure_type const&) = delete;
void operator()() const { /*return call();*/ }
operator decltype(&call)() const
{
return &call;
}
};
As you may have noted, the conversion operator returns the same function pointer each time. Though it would be utterly surprising if anything the like happened, the standard does allow different function pointers to be returned for a call to the conversion operator for the same closure object; A comparison of two closure objects has therefore an implementation-defined value. (It should, though, on all implementations be true for two closure objects of the same type.)