Semi-Common Function

I have many overloaded functions that work with certain data types, such as int, double and strings. Most of these functions perform the same action where only a specific set of data types is allowed. This means that I cannot create a simple general template function, since I will lose type safety (and there may be a runtime problem for checking inside the function).

Is it possible to create a β€œhalf-copied function like compile time"? If so, how? If not, is this something that will appear in C ++ 0x?

Idea (invalid);

template <typename T, restrict: int, std::string > void foo(T bar); ... foo((int)0); // OK foo((std::string)"foobar"); // OK foo((double)0.0); // Compile Error 

Note. I understand that I can create a class with overloaded constructors and assignment operators and pass a variable to this class instead of a function.

+4
source share
5 answers

Use sfinae

 template<typename> struct restrict { }; template<> struct restrict<string> { typedef void type; }; template<> struct restrict<int> { typedef void type; }; template <typename T> typename restrict<T>::type foo(T bar); 

That foo will be able to accept string or int for T Calling foo(0.f) does not cause a hard compile-time error, but if there is another function that takes an argument, it is executed instead.

+5
source

You can create a template function "private" that is never exposed to the outside, and call it from your "safe" overloads.

By the way, usually there is a problem with the direct representation of the template version: if the transferred type is not suitable for it, a compilation error will be generated (if you do not know that your algorithm can detect subtle errors with some data types).

+1
source

Perhaps a bit ugly solution, but functors can be an option:

 class foo { void operator()(double); // disable double type public: template<typename T> void operator ()(T bar) { // do something } }; void test() { foo()(3); // compiles foo()(2.3); // error } 

Edit: I drew my decision

 class foo { template<typename T> void operator ()(T bar, void* dummy) { // do something } public: // `int` is allowed void operator ()(int i) { operator ()(i, 0); } }; foo()(2.3); // unfortunately, compiles foo()(3); // compiles foo()("hi"); // error 
0
source

You could probably work with template specializations for the "restricted" types that you want to allow. For all other types, you do not provide template specialization, so a common β€œbase” template will be used. There you can use something like BOOST_STATIC_ASSERT to throw a compilation error.

Here is some pseudo code to clarify my idea:

 template <typename T> void foo(T bar) {BOOST_STATIC_ASSERT(FALSE);} template<> // specialized for double void foo(double bar) {do_something_useful(bar);}; 
0
source

To indicate an arbitrary choice of types, suppose you can use a list of types. For example, see the last part of my earlier answer .

Usage may look something like this:

 //TODO: enhance typelist declarations to hide the recursiveness typedef t_list<std::string, t_list<int> > good_for_foo; template <class T> typename boost::enable_if<in_type_list<T, good_for_foo> >::type foo(T t); 
0
source

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


All Articles