user2975538
user2975538

Reputation: 3

Why does the C++ function template code not compile?

I have searched the web, but I could not find the answer to my problem> Why does the C++ template code not compile? Once I remove the last line before the return statement, it compiles and runs as expected.

I use g++ version 4.3.4. I will greatly appreciate the expert help.

Regards, maicah

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <stdint.h>
#include <boost/lexical_cast.hpp>

void mult(int* ptr)
{
 std::cout << "void mult(" << *ptr  << "): line: " << __LINE__  << ", function: "<<    __FUNCTION__ << std::endl;
}

template <typename T>
void multIndirect(T* x)
{
    std::cout << "void mult(" << *x  << "): line: " << __LINE__  << ", function: "<< __FUNCTION__ << std::endl;
}

void apply(void (*funcPtr)(int*), int* pVal)
{
    std::cout << "apply(" << boost::lexical_cast<std::string>((uintptr_t) funcPtr)  << ", "  << *pVal << "): line:"  << __LINE__  << ", function: " << __FUNCTION__ << std::endl;
    funcPtr(pVal);
}

template <typename Func, typename T>
void applyIndirect(Func funcPtr, T* x)
{
  std::cout << "apply(" << boost::lexical_cast<std::string>((uintptr_t) funcPtr)  << ", "  << *x << "): line:"  << __LINE__  << ", function: " << __FUNCTION__ << std::endl;
  funcPtr(x);
}


int main(void) {

int y = 300;

mult(&y);
apply(mult, &y);
apply(multIndirect, &y);
    applyIndirect(multIndirect, &y);
return EXIT_SUCCESS;
}

I get the compiler error:

CPPTemplate.cpp: In function int main():
CPPTemplate.cpp:47: error: no matching function for call to applyIndirect(<unresolved         overloaded function type>, int*)
make: *** [CPPTemplate.o] Error 1

Upvotes: 0

Views: 120

Answers (2)

AnT stands with Russia
AnT stands with Russia

Reputation: 320371

How do you expect the compiler to deduce the actual value of template parameter Func for applyIndirect and, consequently, template parameter T for multIndirect from this call

applyIndirect(multIndirect, &y);

?

In this call multIndirect's T could be double or char or SomeOtherType or anything else. You made your Func parameter a completely free type and you provided the compiler with absolutely no means to figure out what type it is supposed to be. This is what causes the error.

Given your declaration of applyIndirect, to make it compile you have to explicitly tell the compiler the value of T in multIndirect

applyIndirect(multIndirect<int>, &y);

Now knowing the type of multIndirect<int> the compiler will be able to figure out what Func is supposed to be. Or, alternatively, you can explicitly tell the compiler the value of Func in applyIndirect

applyIndirect<void (int *)>(multIndirect, &y);

Knowing the value of Func the compiler will be able to figure out what T for multIndirect is supposed to be.

However, looking at the body of your applyIndirect it looks like you want to use funcPtr with parameter x of type T *. That means that type of funcPtr is not really supposed to be a free type. It is supposed to actually depend on T. Why did you make it a free type then? Why did you introduce that extra template parameter Func? What was the purpose of that?

Instead of introducing an extra template parameter, you should have simply declared your applyIndirect as

template <typename T>
void applyIndirect(void funcPtr(T *), T *x)
{
  funcPtr(x);
}

That would be immediately consistent with how apply is declared.

Now the compiler will understand the link between the type of x and the required type of funcPtr. With such declaration you will be able to call

applyIndirect(multIndirect, &y);

The compiler will figure out from the type of &y that T is int. This, in turn, will mean that the type of funcPtr is void (int *). And that will make it instantiate multIndirect for T == int.

Upvotes: 1

Zeta
Zeta

Reputation: 105876

You have to specify which multIndirect<T> you want to apply indirect:

applyIndirect(multIndirect<int>, &y);

You don't need to specify the type if you use apply, because the compiler infers the correct type:

void apply(void (*funcPtr)(int*), int* pVal);
//         ^^^^^^^^^^^^^^^^^^^^^

Upvotes: 2

Related Questions