Template for function

This question was asked to me in an interview:

Suppose you have a function that can take any arguments and any number of arguments. How could you write a template function for the same?

I do not know the exact answer. can anyone suggest?

+6
source share
4 answers

They tested your understanding of the upcoming C ++ standard. The new feature is called "Variadic Templates" and is as follows:

template<typename... Args> void f( const Args&... args ) { // do something } 

For more complex examples see, for example, this tutorial .

+12
source

In C ++ 03, for any number of arguments in a function template is not possible. However, for any type of argument, you can write:

 template<typename T, typename U> void f( const T & t, const U &u ) { //... } 
+4
source

I agree that they most likely looked for variable templates, but for the sake of this, there are different approaches that can be used in C ++ 03:

Using Type Option

Use an option type container. In this case, boost::variant will not work, since it limits the number of types, but you can use boost::any :

 void foo( std::vector< boost::any > args ); 

Compared to variable templates, the user code will be much more cumbersome, because instead of writing foo( a, b, c, d ) , they will have to manually create a vector front. The syntax can be simplified by using variable macros (if the compiler supports them) and or helper template functions to adapt the syntax, but this may well become a mess.

Path C (not pattern):

Use the ellipsis notation to write a function that takes an unknown number of arguments (and types):

 void foo( type x, ... ) 

This approach has many disadvantages. The first is that it is not typical, the compiler will not be able to detect that the arguments are the correct number or types, and this behavior is undefined if any of the arguments is a non-POD type, which limits the use from any type to type PODs, which may or may not be a limiting factor (you can always pass a pointer to an object that is not a POD). In general, it is more difficult to handle and much more error prone, so it should be avoided.

Not answering a question at all

In very few situations, one function should be able to accept an unknown number of arguments of unknown types. This may require registration and I / O, printf . But this can be handled in C ++ by overloading the operator (in particular, operator<< ) and the chain. In a comment, bind was suggested, so yes, perfect forwarding to common code is one such case, bind , std::thread ...

He believes that this is a good answer for the interview, since then you can discuss what the actual need for the function is, and whether there is a better alternative. You could argue that if at the end you need a container of type variant, you can abuse operator overloading to simplify the syntax. An example of this is the boost::assign library, and on these lines you can create an auxiliary argument constructor, as in:

 class args { public: args() {} operator std::vector<boost::any>&() { return v; } template <typename T> args& operator,( T x ) { boost::any a = x; v.push_back( a ); return *this; } private: std::vector<boost::any> v; }; // usage: void foo( std::vector<boost::any> a ) { std::cout << "Received " << a.size() << " arguments" << std::endl; } int main() { foo(( args(), 1, 5.0, "a string", std::vector<int>(5,10) )); } 

Variadic patterns

And, of course, the best option, which is a C ++ 0x compiler that processes variable templates, which does not require additional boiler plate code, and will simplify writing user code (just like a regular function call) and implementing a function, whatever it may be . As a motivating example, we will build a vector<boost::any> with variable arguments:

 typedef std::vector<boost::any> anyvector_t // Stop condition, adding nothing at the end void build_vector_impl( anyvector_t& ) {} // Intermediate step, add a new argument to the vector and recurse: template <typename Head, typename... Tail> void build_vector_impl( anyvector_t& v, Head head, Tail... tail ) { v.push_back( boost::any(head) ); build_vector_impl( v, tail... ); } // Syntactic sugar: make it return the vector: template <typename... Args> anyvector_t build_vector( Args... args ) { anyvector_t res; build_vector_impl( res, args... ); return res; } // Test: int main() { std::cout << "Number of args: " << build_vector( 1, 5, "Hi", std::vector<int>( 5, 10 ) ).size() << std::endl; } 
+2
source

This is not about templates. This is about variable arguments.

http://www.eskimo.com/~scs/cclass/int/sx11b.html

0
source

Source: https://habr.com/ru/post/888690/


All Articles