Skip to content

Instantly share code, notes, and snippets.

@jwpeterson
Last active February 15, 2023 15:35
Show Gist options
  • Save jwpeterson/ed14bcb668b89ff8268db493e75d853a to your computer and use it in GitHub Desktop.
Save jwpeterson/ed14bcb668b89ff8268db493e75d853a to your computer and use it in GitHub Desktop.
Demonstrate usage of noncopyable class in std containers
// Compilation requires -std=c++17
// http://stackoverflow.com/questions/17603666/copy-move-requirements-for-the-key-value-types-in-a-stdmap
#include <map>
#include <vector>
struct foo
{
int i;
foo(int j) : i(j) {}
// make foo non-copyable
foo(const foo &) = delete; // copy ctor
foo & operator=(const foo &) = delete; // assignment op
// Use default move ctors. You have to declare these, otherwise the
// class will not have automatically generated move ctors.
// foo (foo && other) = default;
foo & operator=(foo &&) = default;
// Non-default version of move ctor. Use noexcept to maintain the
// "strong exception guarantee". This is especially important for
// classes which are to be used in std containers -- the container
// may instead use the copy constructor (assuming it's not deleted)
// if the move constructor is not marked noexcept! Neither GCC nor
// clang seem to care whether noexcept is used in this case...
foo (foo && other) noexcept :
i(std::move(other.i))
{}
};
// Required for foo to be used as a key in std::map
bool operator<(const foo & f1, const foo & f2)
{
return f1.i < f2.i;
}
int main(int argc, char ** argv)
{
// Test whether we can create a map where keys are non-copyable. We
// can, but the map itself cannot be copied (makes sense).
{
std::map<foo, int> f;
// std::map<foo, int> f2 = f; // compile error - can't copy map with uncopyable items
std::map<foo, int> f3 = std::move(f); // OK: when moving, nothing is copied
}
// Test whether we can create a map where values are non-copyable.
{
std::map<int, foo> f;
std::map<int, foo> f3 = std::move(f); // OK: when moving, nothing is copied
}
// Test inserting noncopyable keys into the map.
{
std::map<foo, int> f;
f.insert(std::make_pair(foo(1), 1)); // works if foo has move ctor
f[foo(1)] = 1; // works if foo has move ctor
f.emplace(std::make_pair(foo(1), 1)); // works if foo has move ctor
f.emplace(foo(1), 1); // works if foo has move ctor
f.emplace_hint(/*hint=*/f.begin(), foo(1), 1);
f.try_emplace(foo(1), 1);
f.try_emplace(/*hint=*/f.begin(), foo(1), 1);
}
// Test non-copyable items in std::vector.
{
std::vector<foo> f;
f.push_back(foo(1)); // works if foo has move ctor
f.emplace_back(foo(1)); // works if foo has move ctor
f.emplace_back(1); // works by forwarding the arg to the foo ctor
}
return 0;
}
@vpshastry
Copy link

Hi Mr Peterson,

I'm using a map of type std::map<long, std::variant<fu2::unique_function<Type1>, fu2::unique_function<Type2>...>> and I can't insert into it. The line below throws error

using CbVariant = std::variant<std::monostate, fu2::unique_function<void(int)>, fu2::unique_function<void(someClassA)>>;
std::map<id_t, CbVariant> cb_map;
fu2::unique_function<void(int)> callback = [](auto a) { std::cout << a; };
cb_map.try_emplace(id, std::move(callback));

Error:

In file included from /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/memory:66:
In file included from /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/stl_uninitialized.h:67:
In file included from /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/ext/alloc_traits.h:34:
/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/alloc_traits.h:514:4: error: no matching function for call to 'construct_at'
          std::construct_at(__p, std::forward<_Args>(__args)...);
          ^~~~~~~~~~~~~~~~~
/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/stl_tree.h:618:23: note: in instantiation of function template specialization 'std::allocator_traits<std::allocator<std::_Rb_tree_node<std::pair<const long, std::variant<std::monostate, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::TopicId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::TopicId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::TopicId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<std::unique_ptr<northguard::client::TopicMetadata, std::default_delete<northguard::client::TopicMetadata>>, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::client::RangeSplitResult, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::RangeId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>>>>>>::construct<std::pair<const long, std::variant<std::monostate, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::TopicId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::TopicId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::TopicId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<std::unique_ptr<northguard::client::TopicMetadata, std::default_delete<northguard::client::TopicMetadata>>, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::client::RangeSplitResult, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::RangeId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>>>, long &, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::TopicId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>>' requested here
              _Alloc_traits::construct(_M_get_Node_allocator(),
                             ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/stl_tree.h:635:4: note: in instantiation of function template specialization 'std::_Rb_tree<long, std::pair<const long, std::variant<std::monostate, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::TopicId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::TopicId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::TopicId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<std::unique_ptr<northguard::client::TopicMetadata, std::default_delete<northguard::client::TopicMetadata>>, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::client::RangeSplitResult, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::RangeId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>>>, std::_Select1st<std::pair<const long, std::variant<std::monostate, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::TopicId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::TopicId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::TopicId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<std::unique_ptr<northguard::client::TopicMetadata, std::default_delete<northguard::client::TopicMetadata>>, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::client::RangeSplitResult, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::RangeId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>>>>, std::less<long>, std::allocator<std::pair<const long, std::variant<std::monostate, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::TopicId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::TopicId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::TopicId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<std::unique_ptr<northguard::client::TopicMetadata, std::default_delete<northguard::client::TopicMetadata>>, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::client::RangeSplitResult, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::RangeId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>>>>>::_M_construct_node<long &, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::TopicId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>>' requested here
          _M_construct_node(__tmp, std::forward<_Args>(__args)...);
          ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/stl_tree.h:2414:19: note: in instantiation of function template specialization 'std::_Rb_tree<long, std::pair<const long, std::variant<std::monostate, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::TopicId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::TopicId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::TopicId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<std::unique_ptr<northguard::client::TopicMetadata, std::default_delete<northguard::client::TopicMetadata>>, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::client::RangeSplitResult, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::RangeId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>>>, std::_Select1st<std::pair<const long, std::variant<std::monostate, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::TopicId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::TopicId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::TopicId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<std::unique_ptr<northguard::client::TopicMetadata, std::default_delete<northguard::client::TopicMetadata>>, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::client::RangeSplitResult, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::RangeId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>>>>, std::less<long>, std::allocator<std::pair<const long, std::variant<std::monostate, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::TopicId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::TopicId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::TopicId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<std::unique_ptr<northguard::client::TopicMetadata, std::default_delete<northguard::client::TopicMetadata>>, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::client::RangeSplitResult, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::RangeId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>>>>>::_M_create_node<long &, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::TopicId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>>' requested here
        _Link_type __z = _M_create_node(std::forward<_Args>(__args)...);
                         ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/stl_map.h:577:16: note: in instantiation of function template specialization 'std::_Rb_tree<long, std::pair<const long, std::variant<std::monostate, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::TopicId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::TopicId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::TopicId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<std::unique_ptr<northguard::client::TopicMetadata, std::default_delete<northguard::client::TopicMetadata>>, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::client::RangeSplitResult, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::RangeId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>>>, std::_Select1st<std::pair<const long, std::variant<std::monostate, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::TopicId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::TopicId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::TopicId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<std::unique_ptr<northguard::client::TopicMetadata, std::default_delete<northguard::client::TopicMetadata>>, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::client::RangeSplitResult, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::RangeId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>>>>, std::less<long>, std::allocator<std::pair<const long, std::variant<std::monostate, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::TopicId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::TopicId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::TopicId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<std::unique_ptr<northguard::client::TopicMetadata, std::default_delete<northguard::client::TopicMetadata>>, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::client::RangeSplitResult, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::RangeId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>>>>>::_M_emplace_unique<long &, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::TopicId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>>' requested here
        { return _M_t._M_emplace_unique(std::forward<_Args>(__args)...); }
                      ^
../northguard/simulator/src/simulator/jni/client/java_client_proxy.cpp:38:20: note: in instantiation of function template specialization 'std::map<long, std::variant<std::monostate, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::TopicId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::TopicId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::TopicId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<std::unique_ptr<northguard::client::TopicMetadata, std::default_delete<northguard::client::TopicMetadata>>, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::client::RangeSplitResult, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::RangeId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>>, std::less<long>, std::allocator<std::pair<const long, std::variant<std::monostate, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::TopicId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::TopicId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::TopicId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<std::unique_ptr<northguard::client::TopicMetadata, std::default_delete<northguard::client::TopicMetadata>>, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::client::RangeSplitResult, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::RangeId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>>>>>::emplace<long &, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::TopicId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>>' requested here
    callbacks_map_.emplace(correlation_id_, std::move(callback));
                   ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/stl_construct.h:94:5: note: candidate template ignored: substitution failure [with _Tp = std::pair<const long, std::variant<std::monostate, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::TopicId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::TopicId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::TopicId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<std::unique_ptr<northguard::client::TopicMetadata, std::default_delete<northguard::client::TopicMetadata>>, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::client::RangeSplitResult, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::RangeId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>>>, _Args = <long &, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::TopicId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>>]: no matching constructor for initialization of 'std::pair<const long, std::variant<std::monostate, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::TopicId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::TopicId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::TopicId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<std::unique_ptr<northguard::client::TopicMetadata, std::default_delete<northguard::client::TopicMetadata>>, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::client::RangeSplitResult, std::error_code, boost::outcome_v2::policy::all_narrow>)>>, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_default>, fu2::abi_400::detail::property<true, false, void (boost::outcome_v2::basic_result<northguard::api::RangeId, std::error_code, boost::outcome_v2::policy::all_narrow>)>>>>'
    construct_at(_Tp* __location, _Args&&... __args)

Any idea here?

Fu2: Unique function that disables copy constructor. And its only movable. https://github.com/Naios/function2

@jwpeterson
Copy link
Author

In the gist I did not test calling try_emplace for a non-copyable value_type. Does your code work if you change it to call regular emplace instead? You may also want to try with more than one compiler, just to see if you get a different result.

@vpshastry
Copy link

I figured out the problem. The Type1 and Type2 are provided by a header file. Like API 1's type is Type1 and API 2's type is Type2 etc. I opened the header file to look and these types are type aliases / template types. Unfortunately some of the base types for these types are same, out of many. For example

using Type1 = uint64_t;
using Type2 = uint64_t;

This was confusing the std::map::try_emplace with their template condition __exactly_once. So, neither did the std::in_place_type_t based constructor (6th in https://en.cppreference.com/w/cpp/utility/variant/variant) work. The final solution is to use std::in_place_index_t based constructor and use the specific index to emplace.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment