Closed MBkkt closed 2 years ago
Your issue is missing a minimalistic reproducible example: I cannot guess from vague chosen identifiers like "Bruh" or "Kek" what is the behaviour you are expecting from the library and whats not working as intended.
Provide an example with no indirections (over unique_ptr
and constructors) please.
Note that noexcept
in function definitions only works on C++17 and above (due to limitations of earlier standards).
@Naios I think its simple, and you are nitpicking, but https://godbolt.org/z/bfYW539YW
For some reason GCC starts with 10 or 11 (forgot) first try to substitute function ctor instead of move ctor
Example of the real usage: Some object that will be stored as ptr to virtual base class, also contains CallbackGuard that contains noexcept functor
@MBkkt I'm not nitpicking. The naming of identifiers is not truly relevant in this example, the indirection however is. If you remove the additional indirections, your problem is instantly visible:
#include "https://raw.githubusercontent.com/Naios/function2/master/include/function2/function2.hpp"
struct FunctorStorage {
explicit FunctorStorage(fu2::unique_function<void() noexcept>) noexcept {}
explicit FunctorStorage(FunctorStorage&&) noexcept {}
};
int main() {
FunctorStorage* fn = nullptr;
FunctorStorage impl{std::move(*fn)};
return 0;
}
It seems like there is something wrong with the SFINAE guarding the constructor which works without noexcept but not with noexcept specified.
Until this gets fixed you can use a tag to differenciate between your constructors:
#include "https://raw.githubusercontent.com/Naios/function2/master/include/function2/function2.hpp"
struct Tag { };
struct FunctorStorage {
explicit FunctorStorage(Tag, fu2::unique_function<void() noexcept>) noexcept {}
explicit FunctorStorage(FunctorStorage&&) noexcept {}
};
struct Base {};
struct Impl : Base {
explicit Impl(FunctorStorage&& s) noexcept : storage{std::move(s)} {}
FunctorStorage storage;
};
int main() {
Impl impl{FunctorStorage{Tag{}, []() noexcept { }}};
return 0;
}
@Naios Btw fix is easy:
template<typename Trait, typename T, bool Callable>
struct is_noexcept_correct_lazy {
static constexpr bool value = invocation::is_noexcept_correct<
Trait::is_noexcept::value,
typename Trait::template callable<T>,
typename Trait::arguments>::value;
};
template<typename Trait, typename T>
struct is_noexcept_correct_lazy<Trait, T, false> {
static constexpr bool value = false;
};
/// Deduces to a true_type if the type T provides the given signature and the
/// signature is noexcept correct callable.
template <typename T, typename Signature,
typename Trait =
type_erasure::invocation_table::function_trait<Signature>>
struct accepts_one
: std::integral_constant<
bool, is_noexcept_correct_lazy<Trait, T,
invocation::can_invoke<typename Trait::template callable<T>,
typename Trait::arguments>::value
>::value> {};
Or
template <typename T, typename Signature,
typename Trait =
type_erasure::invocation_table::function_trait<Signature>>
struct accepts_one
: std::conjunction<invocation::can_invoke<typename Trait::template callable<T>,
typename Trait::arguments>,
invocation::is_noexcept_correct<
Trait::is_noexcept::value,
typename Trait::template callable<T>,
typename Trait::arguments>> {};
Could you PR your first fix that uses is_noexcept_correct_lazy
? std::conjunction
is a C++17 feature and cannot be used by the library (although a polyfill could be used). This is probably a GCC compiler bug (Clang compiles it fine).
Could you PR your first fix that uses is_noexcept_correct_lazy?
Ok
This is probably also a GCC compiler bug (Clang compiles it fine).
I think it's true, it's really strange that it try to substitute to overload with unique_function first instead of move ctor
@Naios
Cannot use noexcept specifier. Looks like a compile time bug. I think something should be sfinae but its not
Commit Hash
last, 035bec21533f484c1b5dd8dd0380109ea431f6a1
Expected Behavior
Should compile
Actual Behavior
Don't compile
Steps to Reproduce
See godbolt
Your Environment