0

EDIT: Just to clarify "t" is successfully called when casted. The compiler knows and does state that it is a function pointer that takes an argument of type int. I supply a null int pointer to break the loop because it is calling itself recursively. It may just be a bug in the compiler.

I am trying to call a function from a template function argument. I would assume that it would be possible to call the function without explicit casting but that does not seem to be the case. Using VC2013.

template<typename T>
void func(T t)
{

    printf("calling func...\n");

    if (t)
    {
        ((void(__cdecl*)(int))t)((int)nullptr);     // explicit casting is successful

        t ((int)nullptr);                           // compile error: ``term does not evaluate to a function taking 1 arguments``

    }

}

void main()
{

    auto pe = func < int > ;
    auto pf = func < void(__cdecl*)(int) >;

    pf(pe);


}
1
  • One suggestion concerning casts: Casting a nullptr to int is obviously rubbish. Guessing what you want to achieve though, I would guess that you want a default-initialized T. E.g. if T is some pointer type, you want a null pointer, if it's an int you want a zero. The way to achieve that is simply T(), like T nil = T();. Commented Jun 1, 2014 at 14:42

3 Answers 3

2

You have the error for func<int> which becomes:

void func(int t)
{
    printf("calling func...\n");

    if (t)
    {
        ((void(__cdecl*)(int))t)((int)nullptr); // bad casting
        t ((int)nullptr);                       // compile error: int is not a callable object
    }
}
Sign up to request clarification or add additional context in comments.

Comments

1

When t is an int, of course you can't treat it like a function. You'll have to specialize the template for ints or use a different function. Also, please forget that there are C-style casts, they only serve to shoot yourself into the foot.

4 Comments

t is not int, t is of type: void (__cdecl*)(int) at the point of failure.
Actually, I just threw the code at GCC (after fixing some obvious bugs) and you can remove the second and third line of main() and it still doesn't compile. I hereby claim that it is as people have suggested here, that you are trying to call an int as a function. Note that your "works with a cast" is no indication that this isn't the case, as the code never actually gets executed, but at compile time the call that is never made must still be valid.
Ok you just verified that template implementation is broken in GCC as well. The code gets executed trust me. The buggy line should be valid code but these compilers are poorly crafted unfortunately.
func<int> is called with a zero as argument, so the code within if(t) is NOT executed, trust me. However, that code still has to be valid and it isn't, as two compilers and several C++ programmers pointed out to you. You're welcome. ;)
0

I don't understand what do you want exactly. But maybe something like this ?:

#include <iostream>
#include <type_traits>

template<typename T>
void call_helper(T value, std::true_type) // value is function
{
    std::cout << "Function" << std::endl;
    value(0);
}

template<typename T>
void call_helper(T value, std::false_type) // value is NOT function
{
    std::cout << "Not function" << std::endl;
    std::cout << value << std::endl;
}

template<typename T>
void call(T value)
{
    call_helper(value, std::is_function<typename std::remove_pointer<T>::type>());
}

int main()
{
    void (*f)(int) = call<int>;
    call(f);
}

live example: http://rextester.com/DIYYZ43213

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.