3

So I have the following bit of code:

template <typename Type>
class Delegate
{
public:
    Delegate(Type x)
    {
    }
};

void Method()
{
}

int main()
{
    Delegate d(&Method);
    return 0;
}

My question is: why can't the compiler deduce the template type based on what's passed into the constructor? The compile error I get is: Argument list for class template Delegate is missing. I understand that, but I thought type inference could overcome this to allow for cleaner syntax.

Jan Hudec
  • 73,652
  • 13
  • 125
  • 172
Will Custode
  • 4,576
  • 3
  • 26
  • 51

2 Answers2

6

Because template parameter deduction only applies to functions. Class templates require parameters explicitly, always.

That's why many templates have a "named constructor" a function that simply constructs a temporary instance, but by virtue of being a function template rather than class template deduces parameters. For example std::make_pair.

C++11 introduced this new meaning of auto that actually allows you to deduce type of variable. So if you have C++11, you can create a "named constructor" for your class, like:

template <typename Type>
Delegate<Type> delegate(Type x) { return Delegate<Type>(x); }

and you can create a variable of deduced type with it like:

auto d = delegate(&Method);

Note, that this deduces d to be exactly the type returned by the initializer (you can have auto & or auto && if you want, but not much beyond that). This is way easier than trying to deduce hypothetical Delegate d(&Method), because that would involve cyclical dependency between deducing the type depending on overload resolution between constructors and the set of viable constructors depending on the deduced type (remember, constructors can be overloaded and types can be partially specialized).

Jan Hudec
  • 73,652
  • 13
  • 125
  • 172
  • After playing around for a while that's what I came up with but I wasn't sure. Thanks for the clarification. Any particular reason why this is the case, though? I mean, it makes sense that constructors could apply type inferencing. – Will Custode Mar 28 '14 at 19:32
  • @WilliamCustode: The rules would be rather convoluted. The good news is that in C++11 you can do it with the `auto` keyword and appropriate named constructor. I've extended the answer with that. – Jan Hudec Mar 28 '14 at 19:35
  • @WilliamCustode: I've tried to add explanation for why `Delegate d(&Method)` would be more difficult than the `auto`. – Jan Hudec Mar 28 '14 at 19:45
1

It's for the same reason that this won't work:

// attempt to create a std::vector<std::string> of ten "x" strings:
std::vector v(10, "x");

In fact, it should result in the very same error message.

Use something like this to use type deduction:

template <class Type>
Delegate<Type> MakeDelegate(Type const &x)
{
    return Delegate<Type>(x);
}

Or just do as you'd do with a std::vector and declare the type explictly.

By the way, main must return int, and arguments of unknown type (i.e. in templates) should be passed with const&.

Christian Hackl
  • 27,051
  • 3
  • 32
  • 62
  • I appreciate the post-notes about main and const, but this was clearly sample code. I have done like you have suggested and made a method that creates the object for you. Thanks! – Will Custode Mar 28 '14 at 19:42
  • You are welcome. But posting code with `void main` has two big disadvantages: 1.) It teaches newbies who are reading your questions the wrong thing. 2.) In GCC, it is a **compiler error**, so you make it harder for people to compile your sample code. – Christian Hackl Mar 28 '14 at 19:46
  • 1
    Arguments of unknown type should generally be passed by const reference, but arguments of _functor_ types are conventionally _passed by value!_ – Jan Hudec Mar 28 '14 at 19:47
  • @JanHudec: Thanks, this is actually more precise than my advice. The same usually goes for iterator types. Of course, it's only a general guideline in any case, not a strict rule. – Christian Hackl Mar 28 '14 at 19:48
  • I think it is completely irrelevant to the question being asked. Anyone reading a c++ question should understand what `main` is. – Will Custode Mar 28 '14 at 20:22
  • You think it is irrelevant to make it easier for people to help you? Copy-and-pasting example code into their editor is often the first thing people do when looking at questions. The more you make them work to make *your* code compilable (or make it produce the same compiler message you want to know more about), the more likely they will just give up and turn to the next interesting question. – Christian Hackl Mar 28 '14 at 20:25