mardi 26 septembre 2017

Wrapping standard library templates for DLL export (need sanity check)

I think I have a pretty good hold on the issues (different implementations, compiled binary differences, etc..) with exporting templates (vector, string, map, etc..) from the std library for a DLL (or lib) . However I find that I also dislike the use of custom vector/list/map classes and find creating an interface in classes to export their functionality to be tedious an repetitive, so I have come to the conclusion that I am just going to try and wrapper said objects to the best of my ability (and accept whatever performance impact that has). That said I was wondering if you all could sanity check what I have done so far.

So this is the road I have gone down (tested with vector first). I have created a class very similar to std::vector just named vector. The intent is to include it from another file inside a namespace so the the new vector doesn't conflict with anything else. I am working on an openCl library at the moment so that's what the code is coming from.

opencl_std.h

#ifndef _opencl_util_opencl_std_h
#define _opencl_util_opencl_std_h

#include "opencl_util_export.h"

#include <string>
#include <vector>

#ifdef opencl_util_EXPORTS
#define OPENCL_UTIL_EXTERN
#else
#define OPENCL_UTIL_EXTERN extern
#endif

namespace cl{namespace util
{

#include "std_wrappers\vector.h"

OPENCL_UTIL_EXTERN template class OPENCL_UTIL_EXPORT ::cl::util::vector<::size_t>;

}}//namespace cl::util

#endif //_opencl_util_opencl_std_h

opencl.cpp

#include "opencl_std.h"

namespace cl{namespace util
{

#include "std_wrappers\vector.cpp"

}}//namespace cl::util

OPENCL_UTIL_EXPORT is the obligatory dllimport/dllexport and OPENCL_UTIL_EXTERN sets the class to extern when importing. std_wrappers\vector.h includes the declaration of the class and std_wrappers\vector.cpp includes the definition. All though the class is a template the split declaration/definition works as the class is explicitly instantiated with this call (as well as exported).

OPENCL_UTIL_EXTERN template class OPENCL_UTIL_EXPORT ::cl::util::vector<::size_t>;

std_wrappers\vector.h

template<class _Ty, class _Alloc=std::allocator<_Ty> >
class vector
{
    typedef typename std::vector<_Ty, _Alloc>::value_type value_type;
    typedef typename std::vector<_Ty, _Alloc>::allocator_type allocator_type;
    typedef typename std::vector<_Ty, _Alloc>::size_type size_type;
    typedef typename std::vector<_Ty, _Alloc>::difference_type difference_type;

    typedef typename std::vector<_Ty, _Alloc>::reference reference;
    typedef typename std::vector<_Ty, _Alloc>::const_reference const_reference;
    typedef typename std::vector<_Ty, _Alloc>::pointer pointer;
    typedef typename std::vector<_Ty, _Alloc>::const_pointer const_pointer;

    typedef typename std::vector<_Ty, _Alloc>::iterator iterator;
    typedef typename std::vector<_Ty, _Alloc>::const_iterator const_iterator;
    typedef typename std::vector<_Ty, _Alloc>::reverse_iterator reverse_iterator;
    typedef typename std::vector<_Ty, _Alloc>::const_reverse_iterator const_reverse_iterator;

public:
    vector() noexcept;
    explicit vector(const _Alloc &alloc) noexcept;
    explicit vector(size_type count);
    vector(size_type count, const value_type &value);
    vector(size_type count, const value_type &value, const _Alloc &alloc);
    vector(const vector<_Ty, _Alloc> &right);
    vector(const vector<_Ty, _Alloc> &right, const _Alloc &alloc);
    vector(vector<_Ty, _Alloc> &&right) noexcept;
    vector(vector<_Ty, _Alloc> &&right, const _Alloc &alloc);

    ~vector();

    vector &operator=(const vector<_Ty, _Alloc> &other);
    vector &operator=(vector<_Ty, _Alloc> &&other);
    vector &operator=(std::initializer_list<_Ty> ilist);

    void assign(size_type count, const _Ty &value);
//    template< class InputIt> void assign(InputIt first, InputIt last);
    void assign(std::initializer_list<_Ty> ilist);

    reference at(size_type pos);
    const_reference at(size_type pos) const;

    reference operator[](size_type pos);
    const_reference operator[](size_type pos) const;

    reference front();
    const_reference front() const;

    reference back();
    const_reference back() const;

    _Ty *data() noexcept;
    const _Ty *data() const noexcept;

    iterator begin() noexcept;
    const_iterator begin() const noexcept;
    const_iterator cbegin() const noexcept;

    iterator end() noexcept;
    const_iterator end() const noexcept;
    const_iterator cend() const noexcept;

    reverse_iterator rbegin() noexcept;
    const_reverse_iterator rbegin() const;
    const_reverse_iterator crbegin() const noexcept;

    reverse_iterator rend() noexcept;
    const_reverse_iterator rend() const noexcept;
    const_reverse_iterator crend() const noexcept;

    bool empty() const noexcept;
    size_type size() const noexcept;
    void reserve(size_type new_cap);
    void clear() noexcept;

    void push_back(const _Ty &value);
    void push_back(_Ty &&value);

    void resize(size_type count);
    void resize(size_type count, const value_type& value);

private:
    std::vector<_Ty, _Alloc> *_vector;
};

std_wrappers\vector.cpp

template<class _Ty, class _Alloc>
vector<_Ty, _Alloc>::vector() noexcept { _vector=new std::vector<_Ty, _Alloc>(); }

template<class _Ty, class _Alloc>
vector<_Ty, _Alloc>::vector(const _Alloc &alloc) noexcept { _vector=new std::vector<_Ty, _Alloc>(alloc); }

template<class _Ty, class _Alloc>
vector<_Ty, _Alloc>::vector(size_type count) { _vector=new std::vector<_Ty, _Alloc>(count); }

template<class _Ty, class _Alloc>
vector<_Ty, _Alloc>::vector(size_type count, const value_type &value) { _vector=new std::vector<_Ty, _Alloc>(count, value); }

template<class _Ty, class _Alloc>
vector<_Ty, _Alloc>::vector(size_type count, const value_type& value, const _Alloc &alloc) { _vector=new std::vector<_Ty, _Alloc>(count, value, alloc); }

template<class _Ty, class _Alloc>
vector<_Ty, _Alloc>::vector(const vector<_Ty, _Alloc> &right) { _vector=new std::vector<_Ty, _Alloc>(*(right._vector)); }

template<class _Ty, class _Alloc>
vector<_Ty, _Alloc>::vector(const vector<_Ty, _Alloc> &right, const _Alloc &alloc) { _vector=new std::vector<_Ty, _Alloc>(*(right._vector), alloc); }

template<class _Ty, class _Alloc>
vector<_Ty, _Alloc>::vector(vector<_Ty, _Alloc> &&right) noexcept { _vector=right._vector; right._vector=new std::vector<_Ty, _Alloc>();  }

template<class _Ty, class _Alloc>
vector<_Ty, _Alloc>::vector(vector<_Ty, _Alloc> &&right, const _Alloc &alloc) { _vector=right._vector; right._vector=new std::vector<_Ty, _Alloc>(alloc); }

template<class _Ty, class _Alloc>
vector<_Ty, _Alloc>::~vector() { delete _vector; }

template<class _Ty, class _Alloc>
vector<_Ty, _Alloc> &vector<_Ty, _Alloc>::operator=(const vector<_Ty, _Alloc> &other) { _vector->operator=(*(other._vector)); return *this;}

template<class _Ty, class _Alloc>
vector<_Ty, _Alloc> &vector<_Ty, _Alloc>::operator=(vector<_Ty, _Alloc> &&other) { delete _vector; _vector=other._vector; other._vector=new std::vector<_Ty, _Alloc>(); return *this; }

template<class _Ty, class _Alloc>
vector<_Ty, _Alloc> &vector<_Ty, _Alloc>::operator=(std::initializer_list<_Ty> ilist) { _vector->operator=(ilist); return *this; }

template<class _Ty, class _Alloc>
void vector<_Ty, _Alloc>::assign(size_type count, const _Ty &value) { _vector->assign(count, value); }

template<class _Ty, class _Alloc>
void vector<_Ty, _Alloc>::assign(std::initializer_list<_Ty> ilist) { _vector->assign(ilist); }

template<class _Ty, class _Alloc>
typename vector<_Ty, _Alloc>::reference vector<_Ty, _Alloc>::at(size_type pos) { return _vector->at(pos); }

template<class _Ty, class _Alloc>
typename vector<_Ty, _Alloc>::const_reference vector<_Ty, _Alloc>::at(size_type pos) const { return _vector->at(pos); }

template<class _Ty, class _Alloc>
typename vector<_Ty, _Alloc>::reference vector<_Ty, _Alloc>::operator[](size_type pos) { return _vector->operator[](pos); }

template<class _Ty, class _Alloc>
typename vector<_Ty, _Alloc>::const_reference vector<_Ty, _Alloc>::operator[](size_type pos) const { return _vector->operator[](pos); };

template<class _Ty, class _Alloc>
typename vector<_Ty, _Alloc>::reference vector<_Ty, _Alloc>::front() { return _vector->front(); }

template<class _Ty, class _Alloc>
typename vector<_Ty, _Alloc>::const_reference vector<_Ty, _Alloc>::front() const { return _vector->front(); }

template<class _Ty, class _Alloc>
typename vector<_Ty, _Alloc>::reference vector<_Ty, _Alloc>::back() { return _vector->back(); }

template<class _Ty, class _Alloc>
typename vector<_Ty, _Alloc>::const_reference vector<_Ty, _Alloc>::back() const { return _vector->back(); }

template<class _Ty, class _Alloc>
_Ty *vector<_Ty, _Alloc>::data() noexcept { return _vector->data(); }

template<class _Ty, class _Alloc>
const _Ty *vector<_Ty, _Alloc>::data() const noexcept { return _vector->data(); }

template<class _Ty, class _Alloc>
typename vector<_Ty, _Alloc>::iterator vector<_Ty, _Alloc>::begin() noexcept { return _vector->begin(); }

template<class _Ty, class _Alloc>
typename vector<_Ty, _Alloc>::const_iterator vector<_Ty, _Alloc>::begin() const noexcept { return _vector->begin(); }

template<class _Ty, class _Alloc>
typename vector<_Ty, _Alloc>::const_iterator vector<_Ty, _Alloc>::cbegin() const noexcept { return _vector->cbegin(); }

template<class _Ty, class _Alloc>
typename vector<_Ty, _Alloc>::iterator vector<_Ty, _Alloc>::end() noexcept { return _vector->end(); }

template<class _Ty, class _Alloc>
typename vector<_Ty, _Alloc>::const_iterator vector<_Ty, _Alloc>::end() const noexcept { return _vector->end(); }

template<class _Ty, class _Alloc>
typename vector<_Ty, _Alloc>::const_iterator vector<_Ty, _Alloc>::cend() const noexcept { return _vector->cend(); }

template<class _Ty, class _Alloc>
typename vector<_Ty, _Alloc>::reverse_iterator vector<_Ty, _Alloc>::rbegin() noexcept { return _vector->rbegin(); }

template<class _Ty, class _Alloc>
typename vector<_Ty, _Alloc>::const_reverse_iterator vector<_Ty, _Alloc>::rbegin() const { return _vector->rbegin(); }

template<class _Ty, class _Alloc>
typename vector<_Ty, _Alloc>::const_reverse_iterator vector<_Ty, _Alloc>::crbegin() const noexcept { return _vector->crbegin(); }

template<class _Ty, class _Alloc>
typename vector<_Ty, _Alloc>::reverse_iterator vector<_Ty, _Alloc>::rend() noexcept { return _vector->rend(); }

template<class _Ty, class _Alloc>
typename vector<_Ty, _Alloc>::const_reverse_iterator vector<_Ty, _Alloc>::rend() const noexcept { return _vector->rend(); }

template<class _Ty, class _Alloc>
typename vector<_Ty, _Alloc>::const_reverse_iterator vector<_Ty, _Alloc>::crend() const noexcept { return _vector->rend(); }

template<class _Ty, class _Alloc>
bool vector<_Ty, _Alloc>::empty() const noexcept { return _vector->empty(); }

template<class _Ty, class _Alloc>
typename vector<_Ty, _Alloc>::size_type vector<_Ty, _Alloc>::size() const noexcept { return _vector->size(); }

template<class _Ty, class _Alloc>
void vector<_Ty, _Alloc>::reserve(size_type new_cap) { _vector->reserve(new_cap); }

template<class _Ty, class _Alloc>
void vector<_Ty, _Alloc>::clear() noexcept { _vector->clear(); }

template<class _Ty, class _Alloc>
void vector<_Ty, _Alloc>::push_back(const _Ty &value) { _vector->push_back(value); }

template<class _Ty, class _Alloc>
void vector<_Ty, _Alloc>::push_back(_Ty &&value) { _vector->push_back(value); }

template<class _Ty, class _Alloc>
void vector<_Ty, _Alloc>::resize(size_type count) { _vector->resize(count); }

template<class _Ty, class _Alloc>
void vector<_Ty, _Alloc>::resize(size_type count, const value_type& value) { _vector->resize(count, value); }

I left out a few functions as I don't believe I can make them work (basically any function that has its own template)

template< class InputIt > vector( InputIt first, InputIt last, 
    const Allocator& alloc = Allocator() );
template< class InputIt > void assign( InputIt first, InputIt last );

and I had to take some care with the rvalue reference function but I think I got it correct.

template<class _Ty, class _Alloc>
vector<_Ty, _Alloc>::vector(vector<_Ty, _Alloc> &&right) noexcept { _vector=right._vector; right._vector=new std::vector<_Ty, _Alloc>();  }

template<class _Ty, class _Alloc>
vector<_Ty, _Alloc>::vector(vector<_Ty, _Alloc> &&right, const _Alloc &alloc) { _vector=right._vector; right._vector=new std::vector<_Ty, _Alloc>(alloc); }

template<class _Ty, class _Alloc>
vector<_Ty, _Alloc> &vector<_Ty, _Alloc>::operator=(vector<_Ty, _Alloc> &&other) { delete _vector; _vector=other._vector; other._vector=new std::vector<_Ty, _Alloc>(); return *this; }

I have compiled and ran this all in VS2015 and everything seems kosher (granted thats not saying much for the rest of the compilers). I am getting a C4661 warning on the explicit template instantiation.

opencl_stl.h(21): warning C4661: 'void cl::util::vector<std::size_t,std::allocator<std::_Ty>>::resize(unsigned __int64)': no suitable definition provided for explicit template instantiation request

but I think that it is purely a warning as it is defined just not before the instantiation happens. I expected the C4251 warning from this line,

std::vector<_Ty, _Alloc> *_vector;

but I didn't see one, considering it is a pointer the compiled versions should agree on its size anyway. Using cl::util::vector<::size_t> from the library works fine. I have even tried to use cl::util::vector and got link warnings as I expected (as it was never instantiated). I plan to do this with some of the other templates, list, map, unordered_map, string, etc... just looking for a check if I missed something.

Running an existing project with CUDA and C++

I am trying to run this project in my laptop. I've the following things installed.

CUDA:

nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2015 NVIDIA Corporation
Built on Tue_Aug_11_14:27:32_CDT_2015
Cuda compilation tools, release 7.5, V7.5.17

GCC:

gcc (Ubuntu 5.4.1-2ubuntu1~16.04) 5.4.1 20160904
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

CMake:

cmake version 3.5.1

During make. The project gives the following error.

/usr/include/c++/5/bits/c++0x_warning.h:32:2: error: #error This file requires compiler and library support for the ISO C++ 2011 standard. This support must be enabled with the -std=c++11 or -std=gnu++11 compiler options.

If I add the set (CMAKE_CXX_STANDARD 11) to CMakesLists.txt in order to support c++ standard 11. I get the following error.

In file included from /usr/include/mrpt/base/include/mrpt/utils.h:25:0,
                 from /home/muazzam/mywork/python/thesis/PD-Flow/scene_flow_visualization.h:24,
                 from /home/muazzam/mywork/python/thesis/PD-Flow/main_scene_flow_visualization.cpp:24:
/usr/include/mrpt/base/include/mrpt/utils/CStream.h:253:8: error: ‘std::enable_if_t’ has not been declared
   std::enable_if_t<is_shared_ptr<T>::value>* = nullptr)
        ^
/usr/include/mrpt/base/include/mrpt/utils/CStream.h:253:19: error: expected ‘,’ or ‘...’ before ‘<’ token
   std::enable_if_t<is_shared_ptr<T>::value>* = nullptr)
                   ^
/usr/include/mrpt/base/include/mrpt/utils/CStream.h:263:8: error: ‘std::enable_if_t’ has not been declared
   std::enable_if_t<!is_shared_ptr<T>::value>* = nullptr)
        ^
/usr/include/mrpt/base/include/mrpt/utils/CStream.h:263:19: error: expected ‘,’ or ‘...’ before ‘<’ token
   std::enable_if_t<!is_shared_ptr<T>::value>* = nullptr)
                   ^
/usr/include/mrpt/base/include/mrpt/utils/CStream.h:261:6: error: ‘template<class RET, class T, class ... R> RET mrpt::utils::CStream::ReadVariant_helper(mrpt::utils::CSerializable::Ptr&, int)’ cannot be overloaded
  RET ReadVariant_helper(
      ^
/usr/include/mrpt/base/include/mrpt/utils/CStream.h:251:6: error: with ‘template<class RET, class T, class ... R> RET mrpt::utils::CStream::ReadVariant_helper(mrpt::utils::CSerializable::Ptr&, int)’
  RET ReadVariant_helper(
      ^
/usr/include/mrpt/base/include/mrpt/utils/CStream.h: In member function ‘void mrpt::utils::CStream::WriteVariant(T)’:
/usr/include/mrpt/base/include/mrpt/utils/CStream.h:314:15: error: use of ‘auto’ in lambda parameter declaration only available with -std=c++14 or -std=gnu++14
   t.match([&](auto& o) { this->WriteObject(o); });
               ^
/usr/include/mrpt/base/include/mrpt/utils/CStream.h: In lambda function:
/usr/include/mrpt/base/include/mrpt/utils/CStream.h:314:45: error: no matching function for call to ‘mrpt::utils::CStream::WriteObject(int&)’
   t.match([&](auto& o) { this->WriteObject(o); });
                                             ^
/usr/include/mrpt/base/include/mrpt/utils/CStream.h:197:7: note: candidate: void mrpt::utils::CStream::WriteObject(const mrpt::utils::CSerializable*) <near match>
  void WriteObject(const CSerializable* o);
       ^
/usr/include/mrpt/base/include/mrpt/utils/CStream.h:197:7: note:   conversion of argument 1 would be ill-formed:
/usr/include/mrpt/base/include/mrpt/utils/CStream.h:198:7: note: candidate: void mrpt::utils::CStream::WriteObject(const mrpt::utils::CSerializable&)
  void WriteObject(const CSerializable& o) { WriteObject(&o); }
       ^
/usr/include/mrpt/base/include/mrpt/utils/CStream.h:198:7: note:   no known conversion for argument 1 from ‘int’ to ‘const mrpt::utils::CSerializable&’
/usr/include/mrpt/base/include/mrpt/utils/CStream.h: At global scope:
/usr/include/mrpt/base/include/mrpt/utils/CStream.h:524:28: error: ‘std::enable_if_t’ has not been declared
 template <typename T, std::enable_if_t<std::is_base_of<
                            ^
/usr/include/mrpt/base/include/mrpt/utils/CStream.h:524:39: error: expected ‘>’ before ‘<’ token
 template <typename T, std::enable_if_t<std::is_base_of<
                                       ^
/usr/include/mrpt/base/include/mrpt/utils/CStream.h: In function ‘mrpt::utils::CStream& mrpt::utils::operator<<(mrpt::utils::CStream&, const mapbox::util::variant<Types ...>&)’:
/usr/include/mrpt/base/include/mrpt/utils/CStream.h:545:17: error: use of ‘auto’ in lambda parameter declaration only available with -std=c++14 or -std=gnu++14
  pObj.match([&](auto& t) { out << t; });
                 ^
In file included from /usr/include/mrpt/base/include/mrpt/utils/TCamera.h:15:0,
                 from /usr/include/mrpt/base/include/mrpt/utils/CImage.h:16,
                 from /usr/include/mrpt/base/include/mrpt/utils.h:38,
                 from /home/muazzam/mywork/python/thesis/PD-Flow/scene_flow_visualization.h:24,
                 from /home/muazzam/mywork/python/thesis/PD-Flow/main_scene_flow_visualization.cpp:24:
/usr/include/mrpt/base/include/mrpt/utils/CConfigFileBase.h: At global scope:
/usr/include/mrpt/base/include/mrpt/utils/CConfigFileBase.h:80:22: error: ‘enable_if_t’ in namespace ‘std’ does not name a template type
      typename = std::enable_if_t<std::is_enum<enum_t>::value>>
                      ^
/usr/include/mrpt/base/include/mrpt/utils/CConfigFileBase.h:80:33: error: expected ‘>’ before ‘<’ token
      typename = std::enable_if_t<std::is_enum<enum_t>::value>>
                                 ^
/usr/include/mrpt/base/include/mrpt/utils/CConfigFileBase.h:96:22: error: ‘enable_if_t’ in namespace ‘std’ does not name a template type
      typename = std::enable_if_t<!std::is_enum<data_t>::value>>
                      ^
/usr/include/mrpt/base/include/mrpt/utils/CConfigFileBase.h:96:33: error: expected ‘>’ before ‘<’ token
      typename = std::enable_if_t<!std::is_enum<data_t>::value>>
                                 ^
In file included from /home/muazzam/mywork/python/thesis/PD-Flow/main_scene_flow_visualization.cpp:24:0:
/home/muazzam/mywork/python/thesis/PD-Flow/scene_flow_visualization.h:93:13: error: ‘COpenGLScenePtr’ in namespace ‘mrpt::opengl’ does not name a type
     opengl::COpenGLScenePtr  scene;
             ^
CMakeFiles/http://ift.tt/2hx1FMj: recipe for target 'CMakeFiles/http://ift.tt/2hx50yN' failed
make[2]: *** [CMakeFiles/http://ift.tt/2hx50yN] Error 1
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/http://ift.tt/2hx1GQn' failed
make[1]: *** [CMakeFiles/http://ift.tt/2hx1GQn] Error 2
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2

Now I've no idea how to make this work. I am stuck in this since one day. Can anyone help me build this project ? Please.

How to implement standard iterators in class

I have classes which are usually using standard containers as underlying fields. For example, I have a class

template <typename T>
class Vec_3D
{
public:
    /* ... */
    std::array<T, 3> vec;
    /* ... */
};

which has only one variable vec and the rest are just functions I need when working with vectors. I want to be able to use range-based for loop such as

Vec_3D<double> vec;
for (double val : vec) {/*...*/}

which should obviusly iterate over std::array<double, 3>.

How to implement iterators in my class which should in turn call iterators of std::array<T, 3>?

I started with this question and tried to define iterators in my class as

typedef std::iterator<std::random_access_iterator_tag, T, ptrdiff_t, T*, T&> iterator;
typedef std::iterator<std::random_access_iterator_tag, const T, ptrdiff_t, const T*, const T&> const_iterator;

inline iterator begin() noexcept { return vec.begin(); }
inline const_iterator cbegin() const noexcept { return vec.cbegin(); }
inline iterator end() noexcept { return vec.end(); }
inline const_iterator cend() const noexcept { return vec.end(); }

but got compiling errors

error: no match for ‘operator!=’ (operand types are ‘Vec_3D<double>::iterator {aka std::iterator<std::random_access_iterator_tag, double, long int, double*, double&>}’ and ‘Vec_3D<double>::iterator {aka std::iterator<std::random_access_iterator_tag, double, long int, double*, double&>}’)

and operator++, operator*

Numbers larger than long long

I am writing a C++ program to generate the series of Fibanachi numbers. This is the 1, 1, 2, 3, 5... series. The 300th number in this series is 359579325206583560961765665172189099052367214309267232255589801. This is well beyond the limits of int or even unsigned long long. How can I continue to represent such large numbers?

Here's my code:

unsigned long long FibLoop(int n)
{
    // Keep track of previous two numbers
    unsigned long long prev[2];
    prev[0] = 1;
    prev[1] = 1;

    // Loop
    for(int i = 2; i <= n; i++)
    {
        prev[i % 2] = prev[0] + prev[1];
        cout << i << "\t" << prev[i % 2] << endl;
    }

    // Return
    return prev[n % 2];
}

C++11 lambda returning reference

I have some trouble to return a reference from a lambda. This code works :

std::function<int*(int*)> funct;

funct = [](int *i){
    ++*i;
    return i;
};

int j = 0;
LOG<<*funct(&j)<<j;

Output : 1 1

But not this one :

std::function<int&(int&)> funct;

funct = [](int &i){
    ++i;
    return i;
};

int j = 0;
LOG<<funct(j)<<j;

Building error : C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\type_traits:1441: error: C2440: 'return': cannot convert from 'int' to 'int &'

Any idea why? For me it is the same thing.

C++ Passing std::function object to variadic template

I want to pass a callable (std::function object) into a class Foo. The callable refers to a member method of another class which has arbitrary arguments, hence the Foo must be a variadic template. Consider this code:

struct Bar {
  void MemberFunction(int x) {}
};

template<typename ...Args>
class Foo {
 public:
  Foo(std::function<void(Bar*, Args...)> f) {}
};

int main() {
  Foo<int> m1(&Bar::MemberFunction);
  return 0;
}

This compiles fine. Now I want to write a factory function MakeFoo() which returns a unique_ptr to a Foo object:

template<typename ...Args>
std::unique_ptr<Foo<Args...>> MakeFoo(std::function<void(Bar*, Args...)> f) {
  return std::make_unique<Foo<Args...>>(f);
}

Using this function by calling

auto m2 = MakeFoo<int>(&Bar::MemberFunction);

in main, gives me the following compiler errors:

functional.cc: In function ‘int main()’:
functional.cc:21:50: error: no matching function for call to ‘MakeFoo(void (Bar::*)(int))’
       auto m2 = MakeFoo<int>(&Bar::MemberFunction);
                                                  ^
functional.cc:15:35: note: candidate: template<class ... Args> std::unique_ptr<Foo<Args ...> > MakeFoo(std::function<void(Bar*, Args ...)>)
     std::unique_ptr<Foo<Args...>> MakeFoo(std::function<void(Bar*, Args...)> f) {
                                   ^
functional.cc:15:35: note:   template argument deduction/substitution failed:
functional.cc:21:50: note:   mismatched types ‘std::function<void(Bar*, Args ...)>’ and ‘void (Bar::*)(int)’
       auto m2 = MakeFoo<int>(&Bar::MemberFunction);

It seems to me, that when I call the constructor of Foo, the compiler happily converts the function pointer &Bar::MemberFunction to a std::function object. But when I pass the same argument to the factory function, it complains. Moreover, this problem only seems to occur, when Foo and MakeFoo are variadic templates. For a fixed number of template parameters it works fine.

Can somebody explain this to me?

How to add two strings mathematically?

Can someone explain how to add 2 strings of integers. I need to make the program, but i don't know where to start. I don't need to concatenate them, I need to add them as integers.