]> git.llucax.com Git - personal/website.git/blob - source/blog/posts/2010/07/25-c++-template-wtf.rst
Update resume with The Podcast App
[personal/website.git] / source / blog / posts / 2010 / 07 / 25-c++-template-wtf.rst
1 Title: C++ template WTF
2 Tags: en, d, c++, template, wtf, programming
3
4 See this small program::
5
6    template<typename T1>
7    struct A {
8            template<typename T2>
9            void foo_A() {}
10    };
11
12    template<typename T>
13    struct B : A<T> {
14            void foo_B() {
15                    this->foo_A<int>(); // line 10
16            }
17    };
18
19    int main() {
20            B<int> b;
21            b.foo_B();
22            return 0;
23    }
24
25 You may think it should compile. Well, it doesn't::
26
27    g++ t.cpp -o t
28    t.cpp: In member function ‘void B<T>::foo_B()’:
29    t.cpp:10: error: expected primary-expression before ‘int’
30    t.cpp:10: error: expected ‘;’ before ‘int’
31
32 Today I've learned a new (**horrible**) *feature* of C++, ``foo_A`` is an
33 ambiguous__ symbol for C++. I've seen the ``typename`` keyword being used to
34 disambiguate types before (specially when using iterators) but never a template.
35 Here is the code that works::
36
37    template<typename T1>
38    struct A {
39            template<typename T2>
40            void foo_A() {}
41    };
42
43    template<typename T>
44    struct B : A<T> {
45            void foo_B() {
46                    this->template foo_A<int>();
47                    //    ^^^^^^^^
48                    // or: A<T>::template foo_A<int>();
49                    // but not simply: template foo_A<int>();
50            }
51    };
52
53    int main() {
54            B<int> b;
55            b.foo_B();
56            return 0;
57    }
58
59 __ http://womble.decadent.org.uk/c++/template-faq.html#disambiguation
60
61 Note how you have to help the compiler, explicitly saying *yes, believe me,
62 foo_A is a template* because it has no clue. Also note that the ``template``
63 keyword is only needed when ``A``, ``B`` and ``A::foo_A`` are all templates;
64 remove the ``template<...>`` to any of them, and the original example will
65 compile flawlessly, so this is a **special special special** case.
66
67 Yeah, really spooky!
68
69 In D__ things are more natural, because templates are not ambiguous (thanks to
70 the odd ``symbol!(Type)`` syntax), you can just write::
71
72    class A(T1) {
73            void foo_A(T2)() {}
74    }
75
76    class B(T) : A!(T) {
77            void foo_B() {
78                    foo_A!(int)();
79            }
80    }
81
82    void main() {
83            B!(int) b;
84            b.foo_B();
85    }
86
87 __ http://digitalmars.com/d/
88
89 And all works as expected.
90
91
92 .. vim: set et sw=3 sts=3 :