Home > OS >  How do I initialize an object using a static member function of that object's class?
How do I initialize an object using a static member function of that object's class?

Time:07-28

I have a class with some static functions. The class constructor takes a function as one of its arguments.

template <typename T>
class MyClass {
    public:
        static std::function<T(T, T)> func1 = [](T a, T b) {
            ...
        }

        static std::function<T(T, T)> func2 = [](T a, T b) {
            ...
        }
     
        MyClass(std::function<T(T, T)> func) {
            ...
        }
}

When I initialize an object from this class:

MyClass<int> myObj(MyClass.func1);

The compiler complains that:

> argument list for class template "MyClass" is missing.

What is the correct way to do this while keeping the functions in the class itself?

CodePudding user response:

MyClass is a template not a class. The class that has a static member you want to pass to the constructor is MyClass<int>.

Your code has some typos (missing ;), I had to add inline for in-class initialization of the static members, I introduced an alias, and for brevity I used struct rather than class (the class has only public members):

#include <iostream>
#include <functional>


template <typename T>
struct MyClass {
    using fun_t = std::function<T(T,T)>;
    static inline fun_t func1 = [](T a, T b) { return a b; };
    static inline fun_t func2 = [](T a, T b) { return a-b; };
    fun_t fun;
    MyClass(std::function<T(T, T)> func) : fun(func) {}
};

int main() {
    auto x = MyClass<int>{MyClass<int>::func1};
    std::cout << x.fun(1,2);
}

As pointed out in comments by AyxanHaqverdili, this would work as well:

auto x = MyClass{ MyClass<int>::func1 };

due to CTAD (class template argument deduction) where the class templates argument is deduced from the constructors parameters. Live Demo

Also this is fine, although a bit hacky, and I don't recommend to actually use it:

MyClass<int> x { x.func1 }; 

In a nutshell: You can refer to a variable in its own initializer. We aren't doing something that would require x to be fully initialized, so there is no problem with accessing the (already initialized) static member via an instance of MyClass<int>. Live Demo

A less suspicious variant of this suggested by @HTNW is

MyClass<int> x{decltype(x)::func1};

Now it is more obvious that we only use the type of x and access a static member of its class.

  •  Tags:  
  • c
  • Related