Question

I was trying to use a functor as a std::function object inside a class template. Below is what I have done so far.

//! the functor class template
template<typename T>
struct func
{
    void operator ()(T t)
    {
        std::cout << t << "\n";
    }
};

//! the class template that holds a std::function object as a member
template<typename T>
struct Foo
{
    std::function<void(T)> bar = func<T>();
};


int main()
{
    Foo<int> foo;
    return 0;
}

It was complained that

error: conversion from 'func<int>' to non-scalar type 'std::function<void(int)>' requested
 struct Foo
        ^

Is it possible to do so? How to fix it?

Was it helpful?

Solution

You can either make it static and initialize it outside class-scope, or initialize it in the constructor. Tested on GCC 4.7.2.

template<typename T>                                                                                
struct Foo                                                                                          
{                                                                                                   
    static std::function<void(T)> bar;                                                                 
};                                                                                                  

template <typename T>                                                                               
std::function<void(T)> Foo<T>::bar = func<T>(); 

EDIT

In C++11, you can also use brace-initialization:

std::function<void(T)> bar { func<T>() };

OTHER TIPS

Different ways to use std::function in a non-static data member initializer

#include <functional>
#include <iostream>

#define ENABLE_CONVERSION 1

template<typename T>
struct func
{
    void operator ()(T t)
    {
        std::cout << "Function: " << t << "\n";
    }

    #if ENABLE_CONVERSION
    // FIX: error: conversion from ‘func<int>’ to non-scalar type
    //      ‘std::function<void(int)>’ requested
    operator std::function<void(T)> () { return std::function<void(T)>(*this); }
    #endif
};

template<typename T>
struct Foo
{
    std::function<void(T)> bar0 = std::function<void(T)>(func<T>());
    std::function<void(T)> bar1{func<T>()};
    // Error without ENABLE_CONVERSION
    std::function<void(T)> bar2 = func<T>();
    static std::function<void(T)> bar3;

    void operator() () {
        bar0(0);
        bar1(1);
        bar2(2);
        bar3(3);
    }
};

template<typename T>
std::function<void(T)> Foo<T>::bar3 = func<T>();

template<typename T>
void goo() {
    // This compiles without ENABLE_CONVERSION:
    // What is the difference to non-static data member initializers ?
    std::function<void(T)> g = func<T>();
    g(4);
}

int main()
{
    Foo<int> foo;
    foo();
    goo<int>();
    return 0;
}

Additional question

I tried to find differences between variable brace-or-equal-initializer and the non-static data member brace-or-equal-initializer. I found nothing.

What is the difference between

std::function<void(T)> bar2 = func<T>();

and

std::function<void(T)> g = func<T>();

when ENABLE_CONVERSION is zero?

In your case std::function is optional, use direct functor itself.

//! the functor class template
template<typename T>
struct func
{
    void operator ()(T t)
    {
        std::cout << t << "\n";
    }
};

//! the class template that holds a std::function object as a member
template<typename T>
struct Foo
{
    //std::function<void(T)> bar = func<T>(); <-- **removed, because std::function isn't cheap as func<T>**.
    func<T> bar;//default initialized itself.
};


int main()
{
    Foo<int> foo;
    foo.bar(24);//prints 24.
    return 0;
}

EDIT: In common case, move template from struct declration to the operator, i.e. as:

struct func
{
   template< typename T >
   void operator()(T t ) const { std::cout << t << '\n'; }
};

struct Foo
{
    func m_func;
};

int main(){
   Foo f;
   f.m_func(24); // prints 24
   f.m_func("hello world"); // prints "hello world"
   f.m_func(3.143); // prints 3.143
   // and etc.,
};

in c++14, std::less<>, std::greater<> and more other functors template keyword moved to the operator declaration, instead of struct declaration, it's help more generic comparation.

Edit2: You may use following technicus:

struct func{  
  template< typename T > void operator()(T t) const{ std::cout << t << '\n';} 
};

template< typename T, typename Functor> // Functor as template
struct Foo
{
    Functor m_Functor; //--> functor member
    T       m_Data; // or something else.
};

// create `makeFoo`  for auto deduced functor type.
template< typename T, typename Functor>
Foo<T,Functor>  makeFoo(Functor f, T t ) { return {f,t}; }

int print(int i, int j){ std::cout << i+j << '\n' ;}

int main()
{
    auto foo = makeFoo(24, func{} );
    // use foo

    auto foo2 = makeFoo("hello", std::bind(print, 2, _1) ); 
   // use foo2
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top