12

Could you explain why the following code doesn't compile? An obvious workaround is to add a 1-argument overload of Apply, is there a simpler one?

template <typename T>
T Identity(const T& i_val)
  {
  return i_val;
  }

template <typename Val, typename Fn>
Val Apply(const Val& v, Fn fn = Identity<Val>)
  {
  return fn(v);
  }

int main() {
  Apply(42);              // error: no matching function for call to 'Apply(int)'
  Apply(42, Identity<int>); // OK
  return 0;
}
8
  • 1
    you have no default value for template. Commented Aug 20, 2012 at 12:33
  • Note that your Identity function always makes a copy -- is that intentional? Commented Aug 20, 2012 at 12:38
  • 1
    @KerrekSB: It is not intentional. Is it relevant to the question? Commented Aug 20, 2012 at 12:44
  • 1
    @Andrey: No, it's just a comment. Commented Aug 20, 2012 at 12:47
  • @KerrekSB: What is a danger if it is making a copy? (probably, it would be a separate question:) ) Commented Aug 20, 2012 at 12:48

3 Answers 3

10

Template argument deduction doesn't work that way -- you can't deduce the type of an argument from a defaulted value. In C++11, you can however specify a default template argument:

template <typename Val, typename Fn = Val(&)(Val const &)>
Val Apply(const Val& v, Fn fn = Identity<Val>)
{
   return fn(v);
}
Sign up to request clarification or add additional context in comments.

2 Comments

Can you please explain your sentence you can't deduce the type of an argument from a defaulted value with example in your answer? thanks
@Mr.Anubis: What I mean is that you can't deduce the type of fn from a value that's given as a defaulted function argument. Argument deduction can only be performed on function arguments that were specified at the call site.
6

Looking up the function to call consists of: 1. creating the set of candidates, which includes template argument deduction 2. determining the best overload

If I understand the standard correctly, only actual function arguments (i.e., not the default ones) take part in deducing the template arguments. Therefore from the argument 42, the only thing the compiler can infer is that Val = int. The overload does not enter the candidate set and the default argument is never looked at.

Comments

0

Apply is a templated function. You need to do Apply<MyValueType,MyFuncType>(42);

You could reasonably expect the compiler to infer Val to be int, but you can't expect it to infer the type of function, even though you've given a default parameter. As a result, it won't infer that you're trying to call that declaration of the Apply function.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.