I have a processing pipeline implemented, but I would like to improve it like this :
#include <iostream>
// buffers
struct src{}; struct b1{}; struct snk{};
// filters
struct f1
{
f1( const src &, b1 & ) { std::cout << "f1( src, b1 )" << std::endl; }
};
struct f2
{
f2( const b1 &, snk & ) { std::cout << "f2( b1, snk )" << std::endl; }
};
// the pipeline
template< typename... Filters >
struct pipeline
{
template< typename LastB >
pipeline( const LastB & )
{}
};
template < typename T1, typename... T >
struct pipeline< T1, T... > : pipeline< T... >
{
template< typename... Buffs, typename Bin, typename Bout >
pipeline( Buffs &... buffs, Bin & bin, Bout & bout ) :
pipeline< T... >( buffs..., bin ),
filter( bin, bout )
{
}
T1 filter;
};
int main()
{
src ba; b1 bb; snk bc;
pipeline< f1 > p1( ba, bb );
pipeline< f1, f2 > p2( ba, bb, bc ); // the problem is in this line!
}
Unfortunately, the example above produces next errors :
sda_variadic.cpp: In function 'int main()':
sda_variadic.cpp:40:39: error: no matching function for call to 'pipeline<f1, f2>::pipeline(src&, b1&, snk&)'
sda_variadic.cpp:40:39: note: candidates are:
sda_variadic.cpp:26:5: note: template<class ... Buffs, class Bin, class Bout> pipeline<T1, T ...>::pipeline(Buffs& ..., Bin&, Bout&)
sda_variadic.cpp:23:8: note: constexpr pipeline<f1, f2>::pipeline(const pipeline<f1, f2>&)
sda_variadic.cpp:23:8: note: candidate expects 1 argument, 3 provided
sda_variadic.cpp:23:8: note: constexpr pipeline<f1, f2>::pipeline(pipeline<f1, f2>&&)
sda_variadic.cpp:23:8: note: candidate expects 1 argument, 3 provided
What is the reason for this error?
How to fix it?
Just a small explanation. I expect that the example above will first create an object of the unspecialized pipeline<>( snk ), then the specialized object pipeline< f1 >(b1,snk), and then the specialized object pipeline< f1, f2 >(src,b1,snk).
btw take a note that the above example works for 1 filter (pipeline< f1).
Since the function parameter pack (
Buffs) is not in the last position, it cannot be deduced. From 14.8.2.1 Deducing template arguments from a function call [temp.deduct.call] paragraph 1:Since you can’t explicitly pass template parameters to a constructor, it can’t be called at all (not that it matters for your problem though).
I’d recommend using
std::tupleto manipulate the variadic arguments, such that you call the constructor like so:pipeline(std::forward_as_tuple(b0, b1, b2), in, out)and an empty tuple would be passed to the last stage.