Is there a way to get the user to explicitly specify the type of the template argument?

Short version: I have a template function that is "universal", but I want to force the user to explicitly specify the type of argument that they pass as an argument to this function.

Any ideas?


Long version: sounds like a terrible design, but here is my case, and I can’t think of anything better now.

I am trying to "implement" ::setsockopt in a small socket class (and I do not want to have many functions by taking different arguments and doing the same thing). For instance:

 template< typename OPTION_VALUE_TYPE > bool set_option( int level, int option_name, const OPTION_VALUE_TYPE& value ) { return -1 != ::setsockopt( fd_, level, option_name, &value, sizeof( value ) ); } 

BUT, this can lead to the following situation: calling set_option with 1 , trying to set the unsigned char parameter will result in an error, since 1 is int . Proper use:

 set_option< unsigned char >( level, option, 1 ); 

a

 set_option( level, option, 1 ); 

will compile fine, but it will be terribly wrong.

+5
source share
2 answers

Yes, you just need to use the template parameter so that it cannot be deduced from the arguments. A common way this is to use typedef in a template class:

 template <typename T> struct identity { typedef T type; }; template <typename OPTION_VALUE_TYPE> bool set_option(int level, int option_name, typename identity<const OPTION_VALUE_TYPE&>::type value); 

To use a type already present in the standard library, you can use enable_if :

 template <typename OPTION_VALUE_TYPE> bool set_option(int level, int option_name, typename std::enable_if<true, const OPTION_VALUE_TYPE&>::type value); 

The reason this prevents the type argument from being output is because the compiler cannot rule out identity specializations: the compiler cannot rule out what you are doing

 template <> struct identity<U> { typedef V type; }; 

where identity<U>::type will no longer be U

+4
source

Place the type of the template in a non-output context, as shown below:

 template <typename T> struct identity { using type = T; }; template <typename OPTION_VALUE_TYPE> bool set_option(int level, int option_name, const typename identity<OPTION_VALUE_TYPE>::type& value); 
+4
source

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


All Articles