0

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?

4
  • 3
    Did you try MyClass<int> myObj(MyClass<int>::func1) ? Commented Jul 28, 2022 at 10:28
  • 1
    You have to specify the T template parameter every time that you want to access it's members: MyClass<int> myObj(MyClass<int>::func1) Commented Jul 28, 2022 at 10:29
  • 1
    Assign a lambda function to static member variable (c++) is not a duplicate of this question. There is no issue with creating static class members here. Commented Jul 28, 2022 at 10:39
  • 2
    Those are not static member functions, they are static member variables. Commented Jul 28, 2022 at 10:45

1 Answer 1

2

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.

Sign up to request clarification or add additional context in comments.

7 Comments

@AyxanHaqverdili good point about CTAD, though its kind of orthogonal, and would require more explanation. And the latter is also interesting, but nasty ;). I'll give it a try...
I would honestly consider MyClass<int> x{x.func1}; or MyClass<int> x{decltype(x)::func1}; as preferred. It ensures func1 comes from the right class even if the type of x changes and it clearly states the type of x.
@HTNW I dont like MyClass<int> x{x.func1}; because one has to inspect the class to see that it is not a problem. With MyClass<int> x{decltype(x)::func1}; its both obvious, we only care about xs type and access a static member of the class.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.