static constexpr functors

How does one use a functor as a static constexpr member?

I had this basic functor for a class:
1
2
3
struct functor{
    short operator()(char c)const{return c-'0';}
};


And in the class, I use it as a static constexpr member:
1
2
3
4
5
6
class Foo{
    public:
//...
    private:
        static constexpr functor k_funky = functor();
};


During the linking stage, I kept getting "undefined reference to 'Foo::k_funky'".
So then I tried declaring the functor's constructor and operator function constexpr:
1
2
3
4
struct functor{
    constexpr short operator()(char c){return c-'0';}
    constexpr functor() = default; //This counts, doesn't it?
};


But I received the same error.

I appreciate any help.

~Daleth~
Compiles cleanly with both clang++ and g++
(with the overloaded call operator constexpr operator()(char c) const)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>

struct functor
{
    constexpr short operator()(char c) const { return c - '0' ; }
};

struct foo
{
    static constexpr functor fun {} ;
};

int main() 
{
    constexpr char cstr[ foo::fun( '8' ) + foo::fun( '6' )  ] = "hello world!\n" ;
    std::cout << cstr ; 
}

http://coliru.stacked-crooked.com/a/2c372713eed923ec
Alas, aggregate initialization seems not to have worked. The same error pops up.

The functor type is actually passed as a template parameter (could that be why I get this problem?).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
struct functor{
    constexpr short operator()(char c)const{return c-'0';}
};

template <class Converter_Type>
class Foo{
    public:
        using converter_t = Converter_Type;
    private:
        static constexpr converter_t k_convert {};
};

//I use a separate file for defining member functions of Foo<Converter_Type>,
//    and those functions use the functor. However, I #include that file right
//    after the class definition. 


If you would like, I can post a link to my code, but it's pretty messy and clumped (I plan on making it more legible once I'm 100% sure everything works).
> The functor type is actually passed as a template parameter
> (could that be why I get this problem?).

No. To pin-point the source of the error one would have to see the code.

But the cause of the error is easy to identify:
somewhere, (in the code that is not posted), the address of the object is being taken.
(Perhaps not directly; the code contains a construct that requires the address of the object).

For the address to be taken, the static member must be defined, and that has not been done.

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
template < typename FN > struct foo
{
    static constexpr int bar() { return fn(100) ; }

    constexpr int baz() const { return fn(100) ; }

    static constexpr FN fn {} ;
};

struct functor
{
   constexpr int operator() ( int a ) const { return a + 56 ; }
};

#include <iostream>
#include <type_traits>

int main()
{
     constexpr foo<functor> object ;

     std::integral_constant< int, foo<functor>::bar() + object.baz() > c ;
     std::cout << "value of c is: " << c << ' ' ;

     const functor& ref_functor = foo<functor>::fn ;
     std::cout << " and value of ref_functor(100) is: " << ref_functor(100) << '\n' ;

#ifdef TAKE_ITS_ADDRESS
     std::cout << "address is: " << std::addressof( foo<functor>::fn ) << '\n' ;
#endif // TAKE_ITS_ADDRESS
}

#ifdef DEFINE_IT
template < typename FN > constexpr FN foo<FN>::fn ;
#endif // DEFINE_IT 

http://coliru.stacked-crooked.com/a/0932152ffc4d34b0
Oh... Shows how little I understand of static members.
My code works perfectly now, thanks!
Topic archived. No new replies allowed.