q0987
q0987

Reputation: 36002

C++ -- In which case the compiler can deduce the type

vector<Widget*> vwp;

// populate vwp;

// Do need to specify the TYPE 'Widget'
for_each(vwp.begin(), vwp.end(), DeleteObject<Widget>()); // case I

template<typename T>
struct DeleteObject: public unary_function<const T*, void> {
    void operator() (const T* ptr) const
    {
      delete ptr;
    }
};

///////////////////////////////////////////////////////////

struct DeleteObjectB {
    template<typename T>
    void operator() (const T* ptr) const
    {
      delete ptr;
    }
};

vector<Widget*> vwpB;

// populate vwpB;

// Do not need to specify the TYPE 'Widget'
for_each(vwpB.begin(), vwpB.end(), DeleteObjectB()); // case II

My question is as follows:

In case I, we need to specify the type.
In case II, we don't need to specify the type.
Is there a general rule that I can follow?

Thank you

Upvotes: 1

Views: 110

Answers (3)

Ise Wisteria
Ise Wisteria

Reputation: 11669

In case II, sometimes operator() is called statically polymorphic. As you mentioned, probably case II is handier in many cases since compiler can deduce the argument type. However, in current C++, sometimes polymorphic operator() doesn't suit.
For example, if the operator() has the signature:

struct DeleteObjectB {
    template<typename T>
    T operator() (const T*) ...

then we cannot pass this DeleteObjectB to some binder like std::bind1st, boost::bind or similar one. Those binders require nested typedef result_type as the resultant type of operator(). So, in this case, we need case I.

Upvotes: 0

Xeo
Xeo

Reputation: 131907

Simple: In the first case, you got nothing to deduce the template type from... how would you? :P In general, for class templates you need to specify the type and (correct me if I'm wrong) can never deduce it.
In your second case, the compiler can deduce the type because you pass an object of type Widget* to that operator(). That's how the compiler sees "Ah, incoming Widget* here, now I know what T should be!"

// Call:
DeleteObject deleter;
Widget* mypwidget;
deleter(mypwidget);
//      ^^^^^^^^^ -- of type `Widget*`, so `T` can be substituted with `Widget*`

Upvotes: 1

Oliver Charlesworth
Oliver Charlesworth

Reputation: 272802

The first case features a class template. The second case features a function template. That is the one distinction.

Upvotes: 4

Related Questions