Skip to content

Lamda used as argument to template function causes illegal specialization to be emitted #4

Description

@muggenhor

Basically, this:

#include <iostream>
#include <utility>

const char* f()
{
  return "Hello World!";
}

template <typename F>
void puts(F&& fn)
{
  std::cout << std::forward<F>(fn)() << "\n";
}

int main()
{
  puts([] {
      return f();
    });
}

Yields this output:

#include <locale>
#include <iostream>
#include <utility>

const char* f()
{
  return "Hello World!";
}

template <typename F>
void puts(F&& fn)
; /* Function Body Removed - Specialization generated */

/*1000000*/
template <>
void  puts<(lambda at ~/git/llvm/temp/test.cpp:18:8)> ( (lambda at ~/git/llvm/temp/test.cpp:18:8) && fn ) {
    std::cout << std::forward<(~/git/llvm/temp/test.cpp:18:8)>(fn)() << "\n";
}

int main()
{
  puts([] {
      return f();
    });
}

While if I use IILE (Immediately-Invoked Lambda Expression) instead of passing the lambda to the puts function I get what's actually decent output (that's also valid C++98):

#include <iostream>

const char* f()
{
  return "Hello World!";
}

int main()
{
  const auto x = [] {
      return f();
    }();
  std::cout << x << "\n";
}

Becomes:

#include <locale>
#include <iostream>

const char* f()
{
  return "Hello World!";
}

int main()
{
 
class LambdaFunctor__11_18 {
public:
static char const  *  lambdaFunc()
{
      return f();
    }
};
 const char *const x = LambdaFunctor__11_18::lambdaFunc();
  std::cout << x << "\n";
}

There's several things wrong with the first produced output. Most obviously that the lambda didn't get a functor class generated and uses of the lambda type replaced by the functor.

More subtly visible errors:

  • The main template (not the specialization) still contains an r-value/universal reference which is illegal C++98
  • The specialization also contains an r-value reference

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    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