Search code examples
c++includeg++c++14generic-lambda

Why does g++ 10.1 complain about a named lambda in a header file and others do not?


I have a header file with a named lambda that I use for measuring the execution time of some functions (the lambda is partially a result of this question How to Write a Lambda Wrapping a Function with Optional Return Value). It resides in a header file that I include from several translation units. This has worked well with g++ 8 and g++ 9. Now when I switch to g++ 10.1 I get an error when linking.

Please check the following reduced example.

Here is the example in Wandbox: https://wandbox.org/permlink/Sizb6txrkW5dkJwT.

File "Lambda.h":

#pragma once

#include <string>

auto measure = [](bool enabled, const std::string& taskName, auto&& function,
        auto&&... parameters) -> decltype(auto)
{
    return std::forward<decltype(function)>(function)(
            std::forward<decltype(parameters)>(parameters)...);
};

File "Test1.cpp":

#include "Lambda.h"

File "Test2.cpp":

#include "Lambda.h"

Then I build like this:

g++ -c Test1.cpp
g++ -c Test2.cpp
g++ -shared -o Test.dll Test1.o Test2.o

Everything works fine up to g++ 9.2, but with g++ 10.1 I get this error message:

ld.exe: Test2.o:Test2.cpp:(.bss+0x0): multiple definition of `measure'; Test1.o:Test1.cpp:(.bss+0x0): first defined here
collect2.exe: error: ld returned 1 exit status

Why? How can I compile my project with g++ 10.1? I use the named lambda like I would use a template function, therefore I need to write my named lambda into a header file to be able to use it anywhere in the project and I cannot somehow separate declaration from definition, right?

I am looking forward to an answer!


Solution

  • I get an error when linking.

    Why?

    Because you violate the One Definition Rule by defining the variable multiple times.

    and others do not?

    Why?

    ¯\_(ツ)_/¯ Language implementations are not required to diagnose ODR violations.

    I use the named lambda like I would use a template function, therefore I need to write my named lambda into a header file to be able to use it anywhere in the project and I cannot somehow separate declaration from definition, right?

    Right.

    How can I compile my project with g++ 10.1?

    Simple solution: Declare the variable inline (C++17 feature).

    As simple, but has curious detail that each TU has their own instance: Declare the variable static.

    Third solution: The lambda captures nothing, so you might as well define a template function instead.

    Fourth solution: Instead of storing the lambda as global variable, write an inline function that returns an instance of the lambda.