// RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify %s // RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify %s // expected-no-diagnostics namespace std { template class function; template class invoker_base { public: virtual ~invoker_base() { } virtual R invoke(Args...) = 0; virtual invoker_base* clone() = 0; }; template class functor_invoker : public invoker_base { public: explicit functor_invoker(const F& f) : f(f) { } R invoke(Args... args) { return f(args...); } functor_invoker* clone() { return new functor_invoker(f); } private: F f; }; template class function { public: typedef R result_type; function() : invoker (0) { } function(const function& other) : invoker(0) { if (other.invoker) invoker = other.invoker->clone(); } template function(const F& f) : invoker(0) { invoker = new functor_invoker(f); } ~function() { if (invoker) delete invoker; } function& operator=(const function& other) { function(other).swap(*this); return *this; } template function& operator=(const F& f) { function(f).swap(*this); return *this; } void swap(function& other) { invoker_base* tmp = invoker; invoker = other.invoker; other.invoker = tmp; } result_type operator()(Args... args) const { return invoker->invoke(args...); } private: invoker_base* invoker; }; } template struct Problem { template constexpr int FuncAlign(int param = alignof(FunctionTemplateParam)); template constexpr int FuncSizeof(int param = sizeof(FunctionTemplateParam)); template constexpr int FuncAlign2(int param = alignof(TemplateParam)); template constexpr int FuncSizeof2(int param = sizeof(TemplateParam)); }; template struct Problem { template constexpr int FuncAlign(int param = alignof(FunctionTemplateParam)); template constexpr int FuncSizeof(int param = sizeof(FunctionTemplateParam)); template constexpr int FuncAlign2(int param = alignof(TemplateParam)); template constexpr int FuncSizeof2(int param = sizeof(TemplateParam)); }; template template constexpr int Problem::FuncAlign(int param) { return 2U*param; } template template constexpr int Problem::FuncSizeof(int param) { return 2U*param; } template template constexpr int Problem::FuncAlign2(int param) { return 2U*param; } template template constexpr int Problem::FuncSizeof2(int param) { return 2U*param; } template <> template constexpr int Problem::FuncAlign(int param) { return param; } template <> template constexpr int Problem::FuncSizeof(int param) { return param; } template <> template constexpr int Problem::FuncAlign2(int param) { return param; } template <> template constexpr int Problem::FuncSizeof2(int param) { return param; } void foo() { Problem p = {}; static_assert(p.FuncAlign() == alignof(char)); static_assert(p.FuncSizeof() == sizeof(char)); static_assert(p.FuncAlign2() == alignof(int)); static_assert(p.FuncSizeof2() == sizeof(int)); Problem q = {}; static_assert(q.FuncAlign() == 2U * alignof(char)); static_assert(q.FuncSizeof() == 2U * sizeof(char)); static_assert(q.FuncAlign2() == 2U *alignof(short)); static_assert(q.FuncSizeof2() == 2U * sizeof(short)); } template class A { public: void run( std::function f1 = [](auto&&) {}, std::function f2 = [](auto&&) {}); private: class Helper { public: explicit Helper(std::function f2) : f2_(f2) {} std::function f2_; }; }; template void A::run(std::function f1, std::function f2) { Helper h(f2); } struct B {}; int main() { A a; a.run([&](auto& l) {}); return 0; }