简体   繁体   中英

Specialized template for function signature

In that test code:

#include <string>
#include <iostream>

using namespace std;

template <typename T> class Signal;

template <typename T, typename U>
class Signal<T (U)>
{
public:
  Signal<T (U)>(T (*ptr)(U))
  {
  }
};

void Print(string const& str)
{
  cout << str << endl;
}

int main(int argc, char *argv[])
{
  Signal<void (string const&)> sig = &Print;
  return 0;
}

Why do I have to write template <typename T> class Signal; ?

Why do I have to specify it ?

You don't have to do what you're doing, but it's the most flexible approach. A one-parameter template with specialization goes like this:

  • A template parametrized on one type...

     template <typename> struct Foo; 
  • ... but it is only defined for function types:

     template <typename R> struct Foo<R()> { /* ... */ }; template <typename R, typename A1> struct Foo<R(A1)> { /* ... */ }; template <typename R, typename ...Args> struct Foo<R(Args...)> { /* ... */ }; 

The alternative would be to hard-code the signature of the function:

  • A class template that stores the function pointer of a one-argument function:

     template <typename R, typename A> struct Bar { R (*fp)(A); Bar(R(*f)(A)) : fp(f) { } // ... }; 

As you can see, the first approach is much more general, as we can specialize Foo for any function type we like. By contrast, the direct template in the second example is intricately tied to the details of the function signature and cannot easily be generalized.

You're creating a specialization of Signal that combines the arbitrary types T and U into the form T(U) . This is put together as the specialization Signal<T(U)> : only one type is in the parameter, which why we forward-declared the Signal taking only one type T . This wouldn't be possible without that declaration.

Here's a simple example:

template <typename T> struct A;

template <typename T, typename U> struct A<T(U)> {

};

int main() {

    A<void(int)> a;

}

The types void and int are bound to the types T and U respectively. This is combined into the type void(int) used in the primary declaration of A to specialize the class.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM