Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / All-Topics

A Workaround for Lambda ODR Violations

0.00/5 (No votes)
13 Jan 2016CPOL1 min read 5.3K  
A workaround for Lambda ODR violations

As brought up in this post with lambdas in inline functions, you can run into ODR violations and thus undefined behavior.

There is also a stack overflow discussion here.

While the ultimate fix may rely on the Core Working Group, I think here is a workaround.

The basis for the trick comes from Paul Fultz II in a post about constexpr lambda. You can find the post here.

Here is some problematic code from the stackoverflow discussion. The lambda may have a different type across translation units and thus result in different specializations of for_each being called for different translation units resulting in ODR violations and thus undefined behavior.

C#
  1  inline void g() {
  2      int arr[2] = {};
  3      std::for_each(arr, arr+2, [] (int i) {std::cout << i << ' ';});
  4  }

Here is a simple fix that will prevent the ODR violation.

C#
  1  // Based on Richard Smith trick for constexpr lambda
  2  // via Paul Fultz II (http://pfultz2.com/blog/2014/09/02/static-lambda/)
  3  template<typename t="">
  4  auto addr(T &&t)
  5  {
  6      return &t;
  7  }
  8  
  9  static const constexpr auto odr_helper = true ? nullptr : addr([](){});
 10  
 11  template <class t="decltype(odr_helper)">
 12  inline void g() {
 13      int arr[2] = {};
 14      std::for_each(arr, arr+2, [] (int i) {std::cout << i << ' ';});
 15  }

We create a static const constexpr null pointer with the type of a lambda. If lambdas are different types across different translation units, then odr_helper will have different types across different translation units. Because g now is a template function using the type of odr_helper, g will be a different specialization across different translation units and thus will not result in an odr violation.

Also note that because T is defaulted, g can be used without any changes from before.

ideone at https://ideone.com/NdBpXN

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)