Click here to Skip to main content
13,738,089 members
Click here to Skip to main content
Add your own
alternative version

Tagged as

Stats

3.1K views
1 bookmarked
Posted 13 Jan 2016
Licenced CPOL

A Workaround for Lambda ODR Violations

, 13 Jan 2016
Rate this:
Please Sign up or sign in to vote.
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.

  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.

  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)

Share

About the Author

John Bandela
Software Developer self employed
United States United States
I started programming in Basic in the 4th grade. In 8th grade, I convinced my parents to buy me Visual C++ 1.0. I discovered I really enjoyed C++, and have been programming in it since. I attended the University of Florida and majored in Computer Science graduating with honors with a 4.0 GPA. I then attending Medical School and obtained my Doctor of Medicine degree.

I have used my computer skills to help me in my medical practice. I also enjoy programming in C++ just for fun, trying to discover new ways of solving problems or applying C++ to new areas. My latest interest has been in creating a component system for C++ allowing components created with 1 compiler to be easily used by another compiler.

You may also be interested in...

Comments and Discussions

 
-- There are no messages in this forum --
Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web06-2016 | 2.8.180920.1 | Last Updated 14 Jan 2016
Article Copyright 2016 by John Bandela
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid