Search code examples
c++templatesnon-type

"could not convert template argument" to its own type


I'm trying to make a type which can type-safely encapsulate arbitrary types. I got the idea in my head that this might be possible from this answer: 5 years later, is there something better than the "Fastest Possible C++ Delegates"? So far I have only succeeded in moving the problem, but I ran into an error that I can't find the root of.

The compiler seems to be telling me that it can't cast the value to the value's own type, which strikes me as bizarre.

I am running Mac OS X 10.6 with llvm-gcc 4.2 (gcc 4.2.1 front-end).

Suggestions of how to get rid of the void* or move it to a less consequential position are welcome, but this question isn't really about that.

The error:

$ g++ main.cpp
main.cpp: In static member function ‘static Stamp StampFactory<T>::make(T*) [with T = int]’:
main.cpp:33:   instantiated from ‘Stamp makeStamp(T*) [with T = int]’
main.cpp:39:   instantiated from here
main.cpp:26: error: could not convert template argument ‘t’ to ‘int*’

The code:

typedef void (*VoidFunc)(void*);

struct Stamp
{
    Stamp(VoidFunc p)
    {
        this->press = p;
    }
    VoidFunc press;
};

template<typename T>
struct StampFactory
{
    template<T* rvalue>
    struct Pattern
    {
        void operator()(void* lvalue)
        {
            *dynamic_cast<T*>(lvalue) = *rvalue;
        }
    };

    static Stamp make(T* t)
    {
        return Stamp(Pattern<t>()); // 28
    }
};

template<typename T>
Stamp makeStamp(T* t)
{
    return StampFactory<T>::make(t); // 33
}

int main(int argc, char** argv)
{
    int i = 0;
    Stamp s = makeStamp(&i); //39
}

Solution

  • The error is due to the fact that template arguments must be compile-time constants (or constexpr), and thus, cannot be a variable (or function parameter). It is allowed to have a pointer as a template argument, but there isn't much that you can feed to it because it needs to be a compile-time constant pointer value (and the only thing I can think of that qualifies is a char-pointer to a string literal). The general rule is simple: All template arguments must be known at compile-time, whether it is a type or a value. This excludes function parameters or other kinds of run-time variables.

    I wish I could suggest an alternative to achieve what you desire, but I can't understand what you are actually trying to do at all.