-
Notifications
You must be signed in to change notification settings - Fork 64
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
port.set(0) in Cpp target generates compile error "ambiguous call of overloaded function" #2280
Comments
This is a very interesting find. Thanks for reporting! I am still puzzeled that this wasn't noticed earlier... and I am not sure how to handle this, or if this is a bug or a feature. It comes down to how we define the semantics of seting or unsetting a port. Currently, in the C++ runtime, we detect if a port is present based on whether it carries a value or not (in which case the value pointer is Any thoughts on this @lhstrh, @edwardalee? |
Another issue is, that I don't know which type the C++ compiler would assign to the |
I would like to see the Cpp target support persistent data, in which case present or absent needs to be encoded some other way. I find this a very useful feature in the C target. |
Yes, implementing persistent ports would actually be relatively simple. However, we should do this conciousiously and have some wider discussion about it. It also comes at the expense of potentially freeing memory for large data structures that are relayed via ports only late (when the value is overwritten vs at the end of the tag). However, persistent ports actually do not solve this particular problem. The problem is that a smart pointer to the value
However, in the case of |
Or we could have a shorthand |
Yes, that could work. Perhaps it wasn't the best idea to overload |
A very C++ way to solve this is template SFINAE, #include <iostream>
#include <type_traits>
template <typename T>
class Port {
public:
Port() = default;
void set(const T& value) {
std::cout << "called (1)" << std::endl;
}
void set(T&& value) {
std::cout << "called (2)" << std::endl;
}
template <typename V, typename = std::enable_if_t< std::is_same_v<V, std::nullptr_t> >>
void set(V) = delete;
};
int main(void) {
Port<int> p_int;
Port<std::string> p_str;
int value = 0;
p_int.set(value); // called (1)
p_int.set(0); // called (2)
// uncommenting below produces compile error
// 'use of deleted function'
// p_int.set(nullptr);
std::string str("hello");
p_str.set(str); // called (1)
p_str.set("hello"); // called (2)
// uncommenting below produces compile error
// 'use of deleted function'
// p_str.set(nullptr);
return 0;
} |
Oh, interesting. That would indeed be a workable solution. I didn't know that |
This pulls in lf-lang/reactor-cpp#57 and adds a new test case. Fixes #2280
Issue: Setting an output port with integral type to the value 0 produces a compile error, unable to disambiguate the call to
set
.LF version: 0.7.0 stable
Workaround 1: Statically cast
.set(static_cast<uint32_t>(0))
Workaround 2: Comment out the line
void set(std::nullptr_t) = delete;
fromport.hh
and runmake
.Steps to recreate:
The line
a.set(0)
produces the following compile error:Note that the port set in the startup reaction does not produce an error, so it is value-dependent.
In the reactor-cpp file
port.hh
, the following overloads forset
are defined:It appears that the value
0
may be castable tostd::nullptr_t
, which makes sense as legacy C code definesNULL
as 0. This creates the ambiguous overload.The text was updated successfully, but these errors were encountered: