array of functions in class->undefined reference

Building upon http://www.cplusplus.com/forum/beginner/4639/ I tried adding it to a class. Keep all functions private and have just one public function to access them. Compilation results in:

1
2
undefined reference to `Thing::functions'
collect2.exe: error: ld returned 1 exit status 


Without any experience and especially lack of vocabulary I can't find a solution. Why does it go wrong and how should I fix it?

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
#include <iostream>
using namespace std;

class Thing {
    private:
        typedef int (Thing::*IntFunc) (int b);
        int function(int b){ return b; }
        int functionTimesTwo(int b){ return b*2; }
        int functionDivideByTwo(int b){ return b/2; }
        static constexpr IntFunc functions[3] = {
            function, 
            functionTimesTwo, 
            functionDivideByTwo
        };
    public:
        int gf(int a, int b){return (this->*functions[a])(b);}
};


int main(){
    Thing thing;

    for(int i = 0; i < 3; ++i){
        int res = thing.gf(i, 8);
        cout << res << endl;
    }
    return 0;
}


TIA,

Ingo
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
#include <iostream>

class Thing {

    private:

        // note: const added to make it const-correct
        typedef int (Thing::*IntFunc) (int b) const ;

        int function(int b) const { return b; }
        int functionTimesTwo(int b) const { return b*2; }
        int functionDivideByTwo(int b) const { return b/2; }

        static constexpr int NUM_FUNCTIONS = 3 ;
        static constexpr IntFunc functions[NUM_FUNCTIONS] = {

            &Thing::function,
            &Thing::functionTimesTwo,
            &Thing::functionDivideByTwo
        };

    public:
        int gf(int a, int b) {

            if( a >= 0 && a < NUM_FUNCTIONS ) return (this->*functions[a])(b);
            else return 0 ; // ideally throw std::out_of_range
        }
};

// Prior to C++17:
// If a constexpr static data member is odr-used, a definition at namespace scope
// is still required, but it cannot have an initializer.
constexpr Thing::IntFunc Thing::functions[Thing::NUM_FUNCTIONS] ; // no initialiser
// Since C++17:
// A constexpr static data member is implicitly inline
// and does not need to be redeclared at namespace scope.
// A redeclaration without an initializer (formerly required)
// is still permitted, but deprecated.
// see: https://en.cppreference.com/w/cpp/language/static#Constant_static_members


int main(){

    Thing thing;

    for(int i = 0; i < 3; ++i) {

        const int res = thing.gf(i, 8);
        std::cout << res << '\n' ;
    }
}

http://coliru.stacked-crooked.com/a/7c3b3b70b4c4ee69
https://rextester.com/MKZH71337
Thank you. A few changes that are obvious in hindsight and the 'big one' that I would have never found.

Thanks again,

Ingo
Topic archived. No new replies allowed.