Why is template deduction fail here?

I’ve got a simple wrapper around bind_front that fails for some reason even before I add my additional code

Here’s the snippet

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>#include <iostream>
#include <functional>
volatile int a1;
volatile int a2;
volatile int a3;
volatile int a4;
volatile int a5;
void foo(int b1, int b2, int b3, int b4, int b5)
{
a1 += b1;
a2 += b2;
a3 += b3;
a4 += b4;
a5 += b5;
}
template <class P, class... Args>
std::function<void(P)> my_bind(void (*method)(Args..., P), Args... args)
{
auto bound = std::bind(method, std::forward<Args>(args)..., std::placeholders::_1);;
return bound;
}
int main(void)
{
std::function<void(int)> a = my_bind(&foo, 1, 2, 3, 4);
std::cout << a1 << " " << a2 << " " << a3 << " " << a4 << " " << a5 << std::endl;
a(5);
std::cout << a1 << " " << a2 << " " << a3 << " " << a4 << " " << a5 << std::endl;
return 0;
}
</code>
<code>#include <iostream> #include <functional> volatile int a1; volatile int a2; volatile int a3; volatile int a4; volatile int a5; void foo(int b1, int b2, int b3, int b4, int b5) { a1 += b1; a2 += b2; a3 += b3; a4 += b4; a5 += b5; } template <class P, class... Args> std::function<void(P)> my_bind(void (*method)(Args..., P), Args... args) { auto bound = std::bind(method, std::forward<Args>(args)..., std::placeholders::_1);; return bound; } int main(void) { std::function<void(int)> a = my_bind(&foo, 1, 2, 3, 4); std::cout << a1 << " " << a2 << " " << a3 << " " << a4 << " " << a5 << std::endl; a(5); std::cout << a1 << " " << a2 << " " << a3 << " " << a4 << " " << a5 << std::endl; return 0; } </code>
#include <iostream>
#include <functional>

volatile int a1;
volatile int a2;
volatile int a3;
volatile int a4;
volatile int a5;

void foo(int b1, int b2, int b3, int b4, int b5)
{
    a1 += b1;
    a2 += b2;
    a3 += b3;
    a4 += b4;
    a5 += b5;       
}

template <class P, class... Args>
std::function<void(P)> my_bind(void (*method)(Args..., P), Args... args)
{
    auto bound = std::bind(method, std::forward<Args>(args)..., std::placeholders::_1);;
    return bound;
}

int main(void)
{
    std::function<void(int)> a = my_bind(&foo, 1, 2, 3, 4);
    std::cout << a1 << " " << a2 << " " << a3 << " " << a4 << " " << a5 << std::endl;
    a(5);
    std::cout << a1 << " " << a2 << " " << a3 << " " << a4 << " " << a5 << std::endl;
    return 0;
}

With clang 18.0.1 I get

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code><source>:28:34: error: no matching function for call to 'my_bind'
28 | std::function<void(int)> a = my_bind(&foo, 1, 2, 3, 4);
| ^~~~~~~
<source>:20:24: note: candidate template ignored: failed template argument deduction
20 | std::function<void(P)> my_bind(void (*method)(Args..., P), Args... args)
| ^
1 error generated.
Compiler returned: 1
</code>
<code><source>:28:34: error: no matching function for call to 'my_bind' 28 | std::function<void(int)> a = my_bind(&foo, 1, 2, 3, 4); | ^~~~~~~ <source>:20:24: note: candidate template ignored: failed template argument deduction 20 | std::function<void(P)> my_bind(void (*method)(Args..., P), Args... args) | ^ 1 error generated. Compiler returned: 1 </code>
<source>:28:34: error: no matching function for call to 'my_bind'
   28 |     std::function<void(int)> a = my_bind(&foo, 1, 2, 3, 4);
      |                                  ^~~~~~~
<source>:20:24: note: candidate template ignored: failed template argument deduction
   20 | std::function<void(P)> my_bind(void (*method)(Args..., P), Args... args)
      |                        ^
1 error generated.
Compiler returned: 1

am I missing something?

If i remove the param P and the placeholder then things work for param less return types

C++ won’t deduce anything after .... ... eats all.

The Args..., P blocks all possibility of deduction occuring. It won’t do “ok, there are 7 items, so 6 go into Args... and the leftover is P“; instead, it will say “stuff after ..., give up immediately.”.

The standard could describe how to solve for deducing stuff after ..., but the standard does not, so it doesn’t work. (How exactly that would work is out of scope for an answer here, as would any problems that would develop if it was allowed).

Now, C++ template metaprogramming is easily powerful enough to actually do what you seem to want. But you have to write the logic yourself.

You’d start with this:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>template <class...A0s, class...A1s>
auto my_bind(void (*method)(A0s...), A1s... args);
</code>
<code>template <class...A0s, class...A1s> auto my_bind(void (*method)(A0s...), A1s... args); </code>
template <class...A0s, class...A1s>
auto my_bind(void (*method)(A0s...), A1s... args);

then write code that “subtracts” the elements of A1s... from A0s...; a really naive one would be to just count and drop them:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>template<class...Ts>
struct types {using type=types;};
template<std::size_t N, class...Ts>
struct drop_types;
template<0, class...Ts>
struct drop_types:types<Ts...>{};
template<std::size_t N, class T0, class...Ts>
struct drop_types<N, T0, Ts...>:drop_types<N-1, Ts...>{};
template<std::size_t N, class...Ts>
using drop_types_t = typename drop_types<N,Ts...>::type;
</code>
<code>template<class...Ts> struct types {using type=types;}; template<std::size_t N, class...Ts> struct drop_types; template<0, class...Ts> struct drop_types:types<Ts...>{}; template<std::size_t N, class T0, class...Ts> struct drop_types<N, T0, Ts...>:drop_types<N-1, Ts...>{}; template<std::size_t N, class...Ts> using drop_types_t = typename drop_types<N,Ts...>::type; </code>
template<class...Ts>
struct types {using type=types;};

template<std::size_t N, class...Ts>
struct drop_types;
template<0, class...Ts>
struct drop_types:types<Ts...>{};
template<std::size_t N, class T0, class...Ts>
struct drop_types<N, T0, Ts...>:drop_types<N-1, Ts...>{};

template<std::size_t N, class...Ts>
using drop_types_t = typename drop_types<N,Ts...>::type;

now we have drop_types_t<sizeof...(A1s), A0s...> as types<A,B,C> from the “tail” of A0s....

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>template<class Sig>
struct build_func;
template<class R, class...Args>
struct build_func<R(Args...)> {
template<class...Ts>
using append = build_func<R, Args..., Ts...>;
using type = std::function<R(Args...)>;
};
template<template<class...>class Z, class types>
struct apply_types;
template<template<class...>class Z, class types>
using apply_types_t = typename apply_types<Z,types>::type;
template<template<class...>class Z, class...Ts>
struct apply_types<Z, types<Ts...>> {
using type = Z<Ts...>;
};
</code>
<code>template<class Sig> struct build_func; template<class R, class...Args> struct build_func<R(Args...)> { template<class...Ts> using append = build_func<R, Args..., Ts...>; using type = std::function<R(Args...)>; }; template<template<class...>class Z, class types> struct apply_types; template<template<class...>class Z, class types> using apply_types_t = typename apply_types<Z,types>::type; template<template<class...>class Z, class...Ts> struct apply_types<Z, types<Ts...>> { using type = Z<Ts...>; }; </code>
template<class Sig>
struct build_func;

template<class R, class...Args>
struct build_func<R(Args...)> {
  template<class...Ts>
  using append = build_func<R, Args..., Ts...>;
  using type = std::function<R(Args...)>;
};

template<template<class...>class Z, class types>
struct apply_types;
template<template<class...>class Z, class types>
using apply_types_t = typename apply_types<Z,types>::type;

template<template<class...>class Z, class...Ts>
struct apply_types<Z, types<Ts...>> {
  using type = Z<Ts...>;
};

then put it together:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>template <class...A0s, class...A1s>
auto my_bind(void (*method)(A0s...), A1s... args)
-> apply_types_t< template build_func<void()>::append, drop_types_t<sizeof...(A1s), A0s...> >
</code>
<code>template <class...A0s, class...A1s> auto my_bind(void (*method)(A0s...), A1s... args) -> apply_types_t< template build_func<void()>::append, drop_types_t<sizeof...(A1s), A0s...> > </code>
template <class...A0s, class...A1s>
auto my_bind(void (*method)(A0s...), A1s... args)
-> apply_types_t< template build_func<void()>::append, drop_types_t<sizeof...(A1s), A0s...> >

the implementation could look like:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>{
return [=](auto&&...extra)->void {
return method( args..., std::forward<decltype(extra)>(extra)... );
};
}
</code>
<code>{ return [=](auto&&...extra)->void { return method( args..., std::forward<decltype(extra)>(extra)... ); }; } </code>
{
  return [=](auto&&...extra)->void {
    return method( args..., std::forward<decltype(extra)>(extra)... );
  };
}

tpyos abound above, so use with caution, but the design should be sound.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật