function2
function2 copied to clipboard
function_view cannot bind to const lambda
@Naios
Expected Behavior
The const-ness of the callable should be propagated to the erased function pointer
Actual Behavior
In file included from main.cpp:1:0:
function2.hpp: In instantiation of ‘static void* fu2::abi_400::detail::type_erasure::address_taker<T, <template-parameter-1-2> >::take(O&&) [with O = const main()::<lambda()>&; T = main()::<lambda()>; <template-parameter-1-2> = void]’:
function2.hpp:1184:51: required from ‘constexpr fu2::abi_400::detail::type_erasure::erasure<false, Config, fu2::abi_400::detail::property<IsThrowing, HasStrongExceptGuarantee, Args ...> >::erasure(T&&) [with T = const main()::<lambda()>&; Config = fu2::abi_400::detail::config<false, true, fu2::capacity_default>; bool IsThrowing = true; bool HasStrongExceptGuarantee = false; Args = {int()}]’
function2.hpp:1376:72: required from ‘constexpr fu2::abi_400::detail::function<Config, fu2::abi_400::detail::property<IsThrowing, HasStrongExceptGuarantee, Args ...> >::function(T&&) [with T = const main()::<lambda()>&; fu2::abi_400::detail::function<Config, fu2::abi_400::detail::property<IsThrowing, HasStrongExceptGuarantee, Args ...> >::enable_if_not_convertible_to_this<T>* <anonymous> = 0; fu2::abi_400::detail::function<Config, fu2::abi_400::detail::property<IsThrowing, HasStrongExceptGuarantee, Args ...> >::enable_if_can_accept_all_t<T>* <anonymous> = 0; fu2::abi_400::detail::function<Config, fu2::abi_400::detail::property<IsThrowing, HasStrongExceptGuarantee, Args ...> >::assert_wrong_copy_assign_t<T>* <anonymous> = 0; fu2::abi_400::detail::function<Config, fu2::abi_400::detail::property<IsThrowing, HasStrongExceptGuarantee, Args ...> >::assert_no_strong_except_guarantee_t<T>* <anonymous> = 0; Config = fu2::abi_400::detail::config<false, true, fu2::capacity_default>; bool IsThrowing = true; bool HasStrongExceptGuarantee = false; Args = {int()}]’
main.cpp:9:42: required from here
function2.hpp:249:26: error: invalid conversion from ‘const void*’ to ‘void*’ [-fpermissive]
return std::addressof(obj);
Steps to Reproduce
#include "function2.hpp"
int main()
{
const auto callable = []{
return 5;
};
fu2::function_view<int()> view(callable);
}
g++ -std=c++14 main.cpp
Your Environment
>$ g++ --version
g++ (GCC) 7.3.1 20180303 (Red Hat 7.3.1-5)
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
From my point of view this is the intended behaviour here because there is no way to access a method qualified as const from a non const context without ignoring the qualifier.
If you want to create a function_view to a const callable object use fu2::function_view<int() const> view(callable);
Implementing it in a way you are proposing would heavily violate the const guarantees provided by the library, because then the constness of an erased object is not propageted to the callable erasure anymore.
Hi, thanks for the fast reply. Firstly, the method you suggest fails with the same error:
#include "function2.hpp"
int main()
{
const auto callable = []{
return 5;
};
fu2::function_view<int() const> view(callable);
}
Secondly I disagree with your final remark. If it is guaranteed that casting any pointer to void* and back will yield the same pointer, and you are not modifying the stored pointer, then I don't see where the violation occurs? This code appears valid to me:
#include "function2.hpp"
#include <iostream>
using func_t = int (*const)();
int main()
{
const auto callable = [](){
return 5;
};
func_t fptr = callable;
void* ptr = (void*)(fptr);
auto cptr = (func_t)(ptr);
std::cout<<cptr()<<'\n';
}
I'm am however happy to be told otherwise, thanks
See folly/function for a basic explanation. It's about halfway down and I quote the beginning:
Other than copyability, there is one more significant difference between std::function and folly::Function, and it concerns const-correctness. std::function does not enforce const-correctness: it allows you to store mutable callables (i.e. callables that may change their inner state when executed, such as a mutable lambda) and call them in a const context (i.e. when you only have access to a const reference to the std::function object). For example ...
That does make sense, so could you explain why my const example doesn't compile?
Seems like there is a bug in the implementation, I'll provide a fix for that soon.
Any update on this? I was testing and noticed
const auto callable = [] {
return 5;
};
fu2::function_view<int() const> view(callable);
still doesn't work
@wak-google Sadly I did not look into this yet. Mainly I thought this issue has not a super high priority.
Any update? :smiley:
Fixed in fa0b7082494c53fd3e393af758088aec54ce6304