Skip to content

Failure to compile cobalt channel in templated code. #263

@17steen

Description

@17steen

I'm trying to use cobalt in conjunction with open62451pp to make calling asynchronous function more linear.

I've implemented a template like such:

template <typename T>
struct AsyncResult<UseCobaltToken, T> {

    template <typename Initiation, typename... Args>
    static auto initiate(Initiation&& initiation, UseCobaltToken, Args&&... args) -> boost::cobalt::task<T> {

        auto ex = co_await boost::cobalt::this_coro::executor;

        auto channel = boost::cobalt::channel<T>(1u, ex);

        auto callback = [&channel, ex](auto&& res) mutable {
            boost::cobalt::spawn(ex,
                    [](auto& chan, auto response) mutable -> boost::cobalt::task<void> {
                        co_await chan.write(std::move(response));
                    }(channel, std::forward<decltype(res)>(res)),
                    boost::asio::detached
                );
        };

        std::invoke(std::forward<Initiation>(initiation), std::move(callback), std::forward<Args>(args)...);

        co_return co_await channel.read();
    }
};

But when compiling, i get the following issue:

[2/2] Linking CXX executable play
FAILED: [code=1] play 
: && /usr/bin/clang++-21 -g -fuse-ld=lld CMakeFiles/play.dir/main.cpp.o -o play  vcpkg_installed/x64-linux-clang21/debug/lib/libfmtd.a  vcpkg_installed/x64-linux-clang21/debug/lib/libboost_cobalt.a  vcpkg_installed/x64-linux-clang21/debug/lib/libopen62541pp.a  vcpkg_installed/x64-linux-clang21/debug/lib/libboost_date_time.a  vcpkg_installed/x64-linux-clang21/debug/lib/libboost_container.a  vcpkg_installed/x64-linux-clang21/debug/lib/libboost_context.a  vcpkg_installed/x64-linux-clang21/debug/lib/libopen62541.a  -lpthread  -lm  -lrt && :
ld.lld: error: undefined symbol: boost::asio::detail::cancellation_handler<boost::cobalt::channel<opcua::Result<opcua::Variant>>::write_op::cancel_impl>::call(boost::asio::cancellation_type)
>>> referenced by main.cpp
>>>               CMakeFiles/play.dir/main.cpp.o:(vtable for boost::asio::detail::cancellation_handler<boost::cobalt::channel<opcua::Result<opcua::Variant>>::write_op::cancel_impl>)

ld.lld: error: undefined symbol: boost::asio::detail::cancellation_handler<boost::cobalt::channel<opcua::Result<opcua::Variant>>::write_op::cancel_impl>::destroy()
>>> referenced by main.cpp
>>>               CMakeFiles/play.dir/main.cpp.o:(vtable for boost::asio::detail::cancellation_handler<boost::cobalt::channel<opcua::Result<opcua::Variant>>::write_op::cancel_impl>)
clang++-21: error: linker command failed with exit code 1 (use -v to see invocation)

I'm compiling with clang++-21 and linking with lld, although, linking with ld also failed.

Other uses of the channel in non templated code, following the example code did compile:
(It's using the same Type when instanciating the channel).

    auto ex = co_await boost::cobalt::this_coro::executor;

    auto chan = std::make_shared<boost::cobalt::channel<opcua::Result<opcua::Variant>>>(1u, ex);

    opcua::services::readValueAsync(client, node,
        [chan, ex](opcua::Result<opcua::Variant> res) {
            fmt::println("Received value: {}, executing coroutine.", res.hasValue() ? "Success" : "Error");
            boost::cobalt::spawn(ex,
                [chan, r = std::move(res)](this auto) -> boost::cobalt::task<void> {
                    co_await chan->write(std::move(r));
                }(),
                boost::asio::detached
            );
    });

Maybe it's a compiler bug on my end? I'm not sure.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions