partial template specialization?

Is it possible to have <void> as a template parameter?
I know that it doesn't work generically, but if you write a specialization for it?
Eg:

1
2
3
4
5
6
7
8
9
10
11
template <typename T>
class MyClass
{
// class definition
};

template<>
class MyClass<void>
{
// etc
};


I'm attempting to do this, however my issue is a little more complicated (there are two template types, T and U, and I want to write specializations where void replaces first T, then U, and then both T and U). What I've written results in an error stating that I have an incomplete type T.

1
2
3
4
5
6
7
template <typename U, typename T>
class MyTemplate
{ /* etc */ }; 

template <>
class MyTemplate<void, class T>
{ /* etc */ };


However, when I attempt to use a member of type T in MyTemplate, I get an error saying that a parameter is of incomplete type T.
Try this:

1
2
3
template <class T>
class MyTemplate<void, class T>
{ /* etc */ };
Last edited on
Nope, it still doesn't work. Maybe I should post the full code?

Note - this is kind of a workaround. Apparently, boost::function and boost::bind would be better to use instead of this, but attempting to do so gives me a headache, so I'm trying to do it via template voodoo.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
/// Now let's do it with templates!
// Where T is the parameter, U is the return type.
template <typename U, typename T>
class ButtonTemplate
{
    public:
        // Pointer to static function with parameters
        // T and void*, returning another type U.
        typedef U (*pFuncsta)(T, void*);
        // Pointer to global function with parameter T
        // and return U.
        typedef U (*pFuncglb)(T);

        ButtonTemplate()
        {
            callbackfunc_    = NULL;
            glbcallbackfunc_ = NULL;
            voidptr_         = NULL;
            param_           = NULL;
        }

        void SetCallbackFunc(pFuncsta func, void* ptr, const T& param)
        {
            glbcallbackfunc_ = NULL;

            callbackfunc_    = func;
            voidptr_         = ptr;
            param_           = param;
        }

        void SetCallbackFunc(pFuncglb func, const T& param)
        {
            callbackfunc_    = NULL;
            voidptr_         = NULL;

            glbcallbackfunc_ = func;
            param_           = &param;
        }

        U DoCallback()
        {
            if (callbackfunc_)
                return callbackfunc_(*param_, voidptr_);
            else if (glbcallbackfunc_)
                return glbcallbackfunc_(*param_);
            else
                std::cerr << "No callback function set." << std::endl;
        }

    private:
        pFuncsta    callbackfunc_;
        pFuncglb    glbcallbackfunc_;
        void*       voidptr_;
        const T*    param_;
};

// Template specialization for a function with void return type.
template <class T>
class ButtonTemplate<void, class T>
{
    typedef void (*pFuncsta)(T, void*);
    typedef void (*pFuncglb)(T);

    public:
        ButtonTemplate()
        {
            callbackfunc_    = NULL;
            glbcallbackfunc_ = NULL;
            voidptr_         = NULL;
            param_           = NULL;
        }

        void SetCallbackFunc(pFuncsta func, void* ptr, const T& param)
        {
            glbcallbackfunc_ = NULL;

            callbackfunc_    = func;
            voidptr_         = ptr;
            param_           = &param;
        }

        void SetCallbackFunc(pFuncglb func, const T& param)
        {
            callbackfunc_    = NULL;
            voidptr_         = NULL;

            glbcallbackfunc_ = func;
            param_           = &param;
        }

        void DoCallback()
        {
            if (callbackfunc_)
                callbackfunc_(*param_, voidptr_);
            else if (glbcallbackfunc_)
                glbcallbackfunc_(*param_);
            else
                std::cerr << "No callback function set." << std::endl;
        }

    private:
        pFuncsta    callbackfunc_;
        pFuncglb    glbcallbackfunc_;
        void*       voidptr_;
        const T*    param_;
};


The ordinary template works fine, so

1
2
3
4
5
6
7
8
9
10
11
int glbsquarefunc(int val)
{ return val*val; }

int main()
{
    ButtonTemplate<int, int> buttontemplate;
    buttontemplate.SetCallbackFunc(&glbsquarefunc, 12);
    std::cout << buttontemplate.DoCallback();

    return 0;
}


works correctly, but since you can't ordinarily do something like ButtonTemplate<void, void> for a function that takes no parameters and returns nothing, I'm trying to write specializations.

By the way, the error I got was similar.
error: using template type parameter 'T' after 'class'
error: template argument 2 is invalid
Oh, sorry, I made a mistake... I meant this:

1
2
3
template <class T>
class MyTemplate<void, T>
{ /* etc */ };

EDIT 1: By the way, why do you need to specialize?
Is it really necessary? This works ok for me:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
using namespace std;

void f() {cout << "asdf" << endl;}
void g() {return f();}

int main()
{
    g();

    cout << "hit enter to quit...";
    cin.get();
    return 0;
}

EDIT 2: Oh, I see... It's the other void (the parameter) that causes the problem.
Last edited on
Well, from what I read here http://lifecs.likai.org/2010/04/c-void-template-parameter.html, it seems like the only way I could set a callback function (in this scenario) that has either a void return type or a void parameter would be to specialize the template for void scenarios

Also, I'm not really sure what your example is supposed to show me :s Care to explain?

Edit2: It works though! Thanks a lot roshi.
Last edited on
Topic archived. No new replies allowed.