I tried to write a very simple variant and visitor implementation as below but I got compile errors that I could not figure out why.
#include <variant>
#include <string>
#include <iostream>
struct foo
{
std::string s;
};
struct bar
{
double s;
};
using var = std::variant<foo, bar>;
struct visitor
{
template <class T>
auto operator()(const T v) -> decltype(v.s)
{
return v.s;
}
};
int main()
{
foo f;
f.s = 3.0;
var x = f;
auto xs = std::visit(visitor{}, x);
std::cout<<xs<<std::endl;
}
The error is so long and is complicate enough to confuse me as a newbie to c++11+
In file included from main.cpp:1:
/usr/local/include/c++/8.1.0/variant: In instantiation of 'static constexpr auto std::__detail::__variant::__gen_vtable_impl<std::__detail::__variant::_Multi_array<_Result_type (*)(_Visitor, _Variants ...)>, std::tuple<_Rest ...>, std::integer_sequence<long unsigned int, __indices ...> >::_S_apply() [with _Result_type = std::__cxx11::basic_string<char> _Visitor = visitor&&; _Variants = {std::variant<foo, bar>&}; long unsigned int ...__indices = {1}]':
/usr/local/include/c++/8.1.0/variant:825:61: required from 'static constexpr void std::__detail::__variant::__gen_vtable_impl<std::__detail::__variant::_Multi_array<_Result_type (*)(_Visitor, _Variants ...), __dimensions ...>, std::tuple<_Variants ...>, std::integer_sequence<long unsigned int, __indices ...> >::_S_apply_single_alt(_Tp&) [with long unsigned int __index = 1; _Tp = std::__detail::__variant::_Multi_array<std::__cxx11::basic_string<char> (*)(visitor&&, std::variant<foo, bar>&)> _Result_type = std::__cxx11::basic_string<char> _Visitor = visitor&&; long unsigned int ...__dimensions = {2}; _Variants = {std::variant<foo, bar>&}; long unsigned int ...__indices = {}]'
/usr/local/include/c++/8.1.0/variant:813:39: required from 'static constexpr void std::__detail::__variant::__gen_vtable_impl<std::__detail::__variant::_Multi_array<_Result_type (*)(_Visitor, _Variants ...), __dimensions ...>, std::tuple<_Variants ...>, std::integer_sequence<long unsigned int, __indices ...> >::_S_apply_all_alts(std::__detail::__variant::__gen_vtable_impl<std::__detail::__variant::_Multi_array<_Result_type (*)(_Visitor, _Variants ...), __dimensions ...>, std::tuple<_Variants ...>, std::integer_sequence<long unsigned int, __indices ...> >::_Array_type&, std::index_sequence<__indices ...>) [with long unsigned int ...__var_indices = {0, 1}; _Result_type = std::__cxx11::basic_string<char> _Visitor = visitor&&; long unsigned int ...__dimensions = {2}; _Variants = {std::variant<foo, bar>&}; long unsigned int ...__indices = {}; std::__detail::__variant::__gen_vtable_impl<std::__detail::__variant::_Multi_array<_Result_type (*)(_Visitor, _Variants ...), __dimensions ...>, std::tuple<_Variants ...>, std::integer_sequence<long unsigned int, __indices ...> >::_Array_type = std::__detail::__variant::_Multi_array<std::__cxx11::basic_string<char> (*)(visitor&&, std::variant<foo, bar>&), 2> std::index_sequence<__indices ...> = std::integer_sequence<long unsigned int, 0, 1>]'
/usr/local/include/c++/8.1.0/variant:803:19: required from 'static constexpr std::__detail::__variant::__gen_vtable_impl<std::__detail::__variant::_Multi_array<_Result_type (*)(_Visitor, _Variants ...), __dimensions ...>, std::tuple<_Variants ...>, std::integer_sequence<long unsigned int, __indices ...> >::_Array_type std::__detail::__variant::__gen_vtable_impl<std::__detail::__variant::_Multi_array<_Result_type (*)(_Visitor, _Variants ...), __dimensions ...>, std::tuple<_Variants ...>, std::integer_sequence<long unsigned int, __indices ...> >::_S_apply() [with _Result_type = std::__cxx11::basic_string<char> _Visitor = visitor&&; long unsigned int ...__dimensions = {2}; _Variants = {std::variant<foo, bar>&}; long unsigned int ...__indices = {}; std::__detail::__variant::__gen_vtable_impl<std::__detail::__variant::_Multi_array<_Result_type (*)(_Visitor, _Variants ...), __dimensions ...>, std::tuple<_Variants ...>, std::integer_sequence<long unsigned int, __indices ...> >::_Array_type = std::__detail::__variant::_Multi_array<std::__cxx11::basic_string<char> (*)(visitor&&, std::variant<foo, bar>&), 2>]'
/usr/local/include/c++/8.1.0/variant:863:38: required from 'static constexpr std::__detail::__variant::__gen_vtable<_Result_type, _Visitor, _Variants>::_Array_type std::__detail::__variant::__gen_vtable<_Result_type, _Visitor, _Variants>::_S_apply() [with _Result_type = std::__cxx11::basic_string<char> _Visitor = visitor&&; _Variants = {std::variant<foo, bar>&}; std::__detail::__variant::__gen_vtable<_Result_type, _Visitor, _Variants>::_Array_type = std::__detail::__variant::_Multi_array<std::__cxx11::basic_string<char> (*)(visitor&&, std::variant<foo, bar>&), 2>]'
/usr/local/include/c++/8.1.0/variant:866:49: required from 'constexpr const std::__detail::__variant::_Multi_array<std::__cxx11::basic_string<char> (*)(visitor&&, std::variant<foo, bar>&), 2> std::__detail::__variant::__gen_vtable<std::__cxx11::basic_string<char>, visitor&&, std::variant<foo, bar>&>::_S_vtable'
/usr/local/include/c++/8.1.0/variant:866:29: required from 'struct std::__detail::__variant::__gen_vtable<std::__cxx11::basic_string<char>, visitor&&, std::variant<foo, bar>&>'
/usr/local/include/c++/8.1.0/variant:1394:23: required from 'constexpr decltype(auto) std::visit(_Visitor&&, _Variants&& ...) [with _Visitor = visitor; _Variants = {std::variant<foo, bar>&}]'
main.cpp:34:38: required from here
/usr/local/include/c++/8.1.0/variant:848:43: error: invalid conversion from 'std::__success_type<double>::type (*)(visitor&&, std::variant<foo, bar>&)' {aka 'double (*)(visitor&&, std::variant<foo, bar>&)'} to 'std::__cxx11::basic_string<char> (*)(visitor&&, std::variant<foo, bar>&)' [-fpermissive]
{ return _Array_type{&__visit_invoke}; }
std::visit requires the return type be same type and value category for all combination:
The return type is deduced from the returned expression as if by decltype. The call is ill-formed if the invocation above is not a valid expression of the same type and value category, for all combinations of alternative types of all variants.
see C++ draft standard [variant.visit]p2:
Requires: For each valid pack m, e(m) shall be a valid expression.
All such expressions shall be of the same type and value category; otherwise, the program is ill-formed.
If for example each struct had an int member x and you return that instead it would not longer be ill-formed see it live on godbolt. In your case you could change the visitor to simply print instead of return the value see it live:
struct visitor
{
template <class T>
void operator()(const T v)
{
std::cout<< v.s;
}
};
Related
I have this class:
template <typename C, typename R, typename D>
class Cache {
typedef std::shared_ptr<cc::Distance<C,D>> DistancePtr;
public:
Cache(const DistancePtr distance, const std::function<R(C)> &backEnd, const size_t size = 10000, const float treshold = 0);
...
private:
struct CacheElem{
CacheElem(const C code, const R result, std::list<size_t>::iterator listElem) : code(code), result(result), listElem(listElem) {}
C code;
R result;
std::list<size_t>::iterator listElem; //pointing to corresponding element in lru0
};
...
I instantiated this object with cc::Cache<int,int,int> cache(...) (I don't know if you need to know all passed arguments, let me know in that case), but I get this error that I don't understand at all:
In file included from /usr/include/c++/5/memory:64:0,
from ../main.cpp:9:
/usr/include/c++/5/bits/stl_construct.h: In instantiation of ‘void std::_Construct(_T1*, _Args&& ...) [with _T1 = cc::Cache<int, int, int>::CacheElem; _Args = {}]’:
/usr/include/c++/5/bits/stl_uninitialized.h:519:18: required from ‘static _ForwardIterator std::__uninitialized_default_n_1<_TrivialValueType>::__uninit_default_n(_ForwardIterator, _Size) [with _ForwardIterator = cc::Cache<int, int, int>::CacheElem*; _Size = long unsigned int; bool _TrivialValueType = false]’
/usr/include/c++/5/bits/stl_uninitialized.h:575:20: required from ‘_ForwardIterator std::__uninitialized_default_n(_ForwardIterator, _Size) [with _ForwardIterator = cc::Cache<int, int, int>::CacheElem*; _Size = long unsigned int]’
/usr/include/c++/5/bits/stl_uninitialized.h:637:44: required from ‘_ForwardIterator std::__uninitialized_default_n_a(_ForwardIterator, _Size, std::allocator<_Tp>&) [with _ForwardIterator = cc::Cache<int, int, int>::CacheElem*; _Size = long unsigned int; _Tp = cc::Cache<int, int, int>::CacheElem]’
/usr/include/c++/5/bits/stl_vector.h:1311:36: required from ‘void std::vector<_Tp, _Alloc>::_M_default_initialize(std::vector<_Tp, _Alloc>::size_type) [with _Tp = cc::Cache<int, int, int>::CacheElem; _Alloc = std::allocator<cc::Cache<int, int, int>::CacheElem>; std::vector<_Tp, _Alloc>::size_type = long unsigned int]’
/usr/include/c++/5/bits/stl_vector.h:279:30: required from ‘std::vector<_Tp, _Alloc>::vector(std::vector<_Tp, _Alloc>::size_type, const allocator_type&) [with _Tp = cc::Cache<int, int, int>::CacheElem; _Alloc = std::allocator<cc::Cache<int, int, int>::CacheElem>; std::vector<_Tp, _Alloc>::size_type = long unsigned int; std::vector<_Tp, _Alloc>::allocator_type = std::allocator<cc::Cache<int, int, int>::CacheElem>]’
/home/luca/Dropbox/HKUST/CloudCache/cloudcache/CloudCache/Core/Cache.hpp:59:85: required from ‘cc::Cache<C, R, D>::Cache(cc::Cache<C, R, D>::DistancePtr, const std::function<R(C)>&, size_t, float) [with C = int; R = int; D = int; cc::Cache<C, R, D>::DistancePtr = std::shared_ptr<cc::Distance<int, int> >; size_t = long unsigned int]’
../main.cpp:33:53: required from here
/usr/include/c++/5/bits/stl_construct.h:75:7: error: no matching function for call to ‘cc::Cache<int, int, int>::CacheElem::CacheElem()’
{ ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); }
^
In file included from ../Core/CCCore.hpp:19:0,
from ../main.cpp:15:
/home/luca/Dropbox/HKUST/CloudCache/cloudcache/CloudCache/Core/Cache.hpp:36:4: note: candidate: cc::Cache<C, R, D>::CacheElem::CacheElem(C, R, std::__cxx11::list<long unsigned int>::iterator) [with C = int; R = int; D = int; std::__cxx11::list<long unsigned int>::iterator = std::_List_iterator<long unsigned int>]
CacheElem(const C code, const R result, std::list<size_t>::iterator listElem) : code(code), result(result), listElem(listElem) {}
^
/home/luca/Dropbox/HKUST/CloudCache/cloudcache/CloudCache/Core/Cache.hpp:36:4: note: candidate expects 3 arguments, 0 provided
/home/luca/Dropbox/HKUST/CloudCache/cloudcache/CloudCache/Core/Cache.hpp:35:10: note: candidate: constexpr cc::Cache<int, int, int>::CacheElem::CacheElem(const cc::Cache<int, int, int>::CacheElem&)
struct CacheElem{
^
/home/luca/Dropbox/HKUST/CloudCache/cloudcache/CloudCache/Core/Cache.hpp:35:10: note: candidate expects 1 argument, 0 provided
/home/luca/Dropbox/HKUST/CloudCache/cloudcache/CloudCache/Core/Cache.hpp:35:10: note: candidate: constexpr cc::Cache<int, int, int>::CacheElem::CacheElem(cc::Cache<int, int, int>::CacheElem&&)
/home/luca/Dropbox/HKUST/CloudCache/cloudcache/CloudCache/Core/Cache.hpp:35:10: note: candidate expects 1 argument, 0 provided
<builtin>: recipe for target 'main.o' failed
make: *** [main.o] Error 1
Why this happen?
UPDATE TO COMMENT ONE ANSWER:
Ok I found out where the problem is, but not why it occours. The Cache constructor implementation is this one:
template <typename C, typename R, typename D>
Cache<C,R,D>::Cache(const DistancePtr distance, const std::function<R(C)> &backEnd, const size_t size, const float treshold)
: distance(distance), backEnd(backEnd), values(size), treshold(treshold), size(size) {}
Where values is declared as:
std::vector<CacheElem> values;
But if I delete values(size) from the constructor above, everything works fine and no compile error occurs. Why? And hot to solve it?
It looks like the problem is that you're missing a default constructor for CacheElem. Somewhere in your code, a CacheElem needs to be default constructed, either because you stored it in an STL container that requires elements to be default constructible, or because you simply tried to instantiate one somewhere without calling a constructor.
I found the error thanks to the tip from this answer.
Changing the Cache constructor implementation from this:
template <typename C, typename R, typename D>
Cache<C,R,D>::Cache(const DistancePtr distance, const std::function<R(C)> &backEnd, const size_t size, const float treshold)
: distance(distance), backEnd(backEnd), values(size), treshold(treshold), size(size) {}
To this:
template <typename C, typename R, typename D>
Cache<C,R,D>::Cache(const DistancePtr distance, const std::function<R(C)> &backEnd, const size_t size, const float treshold)
: distance(distance), backEnd(backEnd), treshold(treshold), size(size) {
values.reserve(size);
}
Solved the problem. I think because calling values(size) is implicitly calling resize() which is illegal without providing CacheElem constructor elements.
Here's what I have so far for an example implementation of a custom constructor in the style of std::pair::pair(std::piecewise_construct_t, ...):
#include <tuple>
#include <string>
#include <utility>
#include <iostream>
struct A {
std::string m_a;
std::string m_b;
std::string m_c;
A() = default;
A(const A&) = default;
A(A&&) = default;
~A() = default;
template <typename T1, typename T2, typename T3>
A(T1&& a, T2&& b, T3&& c) :
m_a { std::forward<T1>(a) }, m_b { std::forward<T2>(b) }, m_c { std::forward<T3>(c) }
{ }
template <typename... T1, typename... T2, typename... T3,
std::size_t... I1, std::size_t... I2, std::size_t... I3>
A(std::tuple<T1...> args1,
std::tuple<T2...> args2,
std::tuple<T3...> args3,
std::integer_sequence<std::size_t, I1...>,
std::integer_sequence<std::size_t, I2...>,
std::integer_sequence<std::size_t, I3...>) :
m_a { std::forward<T1>(std::get<I1>(args1))... },
m_b { std::forward<T2>(std::get<I2>(args2))... },
m_c { std::forward<T3>(std::get<I3>(args3))... }
{ }
template <typename... T1, typename... T2, typename... T3>
A(std::piecewise_construct_t,
std::tuple<T1...> args1,
std::tuple<T2...> args2,
std::tuple<T3...> args3) :
A { args1, args2, args3,
std::make_index_sequence<sizeof...(T1)>{},
std::make_index_sequence<sizeof...(T2)>{},
std::make_index_sequence<sizeof...(T3)>{} }
{ }
};
int main() {
A a { std::piecewise_construct,
std::forward_as_tuple("abc"),
std::forward_as_tuple(10, 'd'),
std::forward_as_tuple("ef\0\0gh", 6)
};
std::cout << "m_a: " << a.m_a <<
"\nm_b: " << a.m_b <<
"\nm_c: " << a.m_c << '\n';
return 0;
}
Expected output (if piped through cat -v):
m_a: abc
m_b: dddddddddd
m_c: ef^#^#gh
However, gcc is still giving me errors that I can't quite decipher, which appear to be related to the internal implementation of std::tuple:
/tmp/from_tuple.cpp: In instantiation of ‘A::A(std::piecewise_construct_t, std::tuple<_Elements ...>, std::tuple<_Elements ...>, std::tuple<_Tail ...>) [with T1 = {const char (&)[4]}; T2 = {int&&, char&&}; T3 = {const char (&)[7], int&&}]’:
/tmp/from_tuple.cpp:51:11: required from here
/tmp/from_tuple.cpp:42:53: error: use of deleted function ‘constexpr std::tuple<_T1, _T2>::tuple(const std::tuple<_T1, _T2>&) [with _T1 = int&&; _T2 = char&&]’
std::make_index_sequence<sizeof...(T3)>{} }
^
In file included from /tmp/from_tuple.cpp:1:0:
/usr/include/c++/5/tuple:615:17: note: ‘constexpr std::tuple<_T1, _T2>::tuple(const std::tuple<_T1, _T2>&) [with _T1 = int&&; _T2 = char&&]’ is implicitly deleted because the default definition would be ill-formed:
constexpr tuple(const tuple&) = default;
^
/usr/include/c++/5/tuple:615:17: error: use of deleted function ‘constexpr std::_Tuple_impl<_Idx, _Head, _Tail ...>::_Tuple_impl(const std::_Tuple_impl<_Idx, _Head, _Tail ...>&) [with long unsigned int _Idx = 0ul; _Head = int&&; _Tail = {char&&}]’
/usr/include/c++/5/tuple:215:17: note: ‘constexpr std::_Tuple_impl<_Idx, _Head, _Tail ...>::_Tuple_impl(const std::_Tuple_impl<_Idx, _Head, _Tail ...>&) [with long unsigned int _Idx = 0ul; _Head = int&&; _Tail = {char&&}]’ is implicitly deleted because the default definition would be ill-formed:
constexpr _Tuple_impl(const _Tuple_impl&) = default;
^
/usr/include/c++/5/tuple:215:17: error: use of deleted function ‘constexpr std::_Tuple_impl<_Idx, _Head>::_Tuple_impl(const std::_Tuple_impl<_Idx, _Head>&) [with long unsigned int _Idx = 1ul; _Head = char&&]’
/usr/include/c++/5/tuple:364:17: note: ‘constexpr std::_Tuple_impl<_Idx, _Head>::_Tuple_impl(const std::_Tuple_impl<_Idx, _Head>&) [with long unsigned int _Idx = 1ul; _Head = char&&]’ is implicitly deleted because the default definition would be ill-formed:
constexpr _Tuple_impl(const _Tuple_impl&) = default;
^
/usr/include/c++/5/tuple:364:17: error: use of deleted function ‘constexpr std::_Head_base<_Idx, _Head, false>::_Head_base(const std::_Head_base<_Idx, _Head, false>&) [with long unsigned int _Idx = 1ul; _Head = char&&]’
/usr/include/c++/5/tuple:110:17: note: ‘constexpr std::_Head_base<_Idx, _Head, false>::_Head_base(const std::_Head_base<_Idx, _Head, false>&) [with long unsigned int _Idx = 1ul; _Head = char&&]’ is implicitly deleted because the default definition would be ill-formed:
constexpr _Head_base(const _Head_base&) = default;
^
/usr/include/c++/5/tuple:110:17: error: copying non-static data member ‘char&& std::_Head_base<1ul, char&&, false>::_M_head_impl’ of rvalue reference type
/usr/include/c++/5/tuple:215:17: error: use of deleted function ‘constexpr std::_Head_base<_Idx, _Head, false>::_Head_base(const std::_Head_base<_Idx, _Head, false>&) [with long unsigned int _Idx = 0ul; _Head = int&&]’
constexpr _Tuple_impl(const _Tuple_impl&) = default;
^
/usr/include/c++/5/tuple:110:17: note: ‘constexpr std::_Head_base<_Idx, _Head, false>::_Head_base(const std::_Head_base<_Idx, _Head, false>&) [with long unsigned int _Idx = 0ul; _Head = int&&]’ is implicitly deleted because the default definition would be ill-formed:
constexpr _Head_base(const _Head_base&) = default;
^
/usr/include/c++/5/tuple:110:17: error: copying non-static data member ‘int&& std::_Head_base<0ul, int&&, false>::_M_head_impl’ of rvalue reference type
/tmp/from_tuple.cpp:23:7: note: initializing argument 2 of ‘A::A(std::tuple<_Elements ...>, std::tuple<_Elements ...>, std::tuple<_Tail ...>, std::integer_sequence<long unsigned int, I1 ...>, std::integer_sequence<long unsigned int, I2 ...>, std::integer_sequence<long unsigned int, I3 ...>) [with T1 = {const char (&)[4]}; T2 = {int&&, char&&}; T3 = {const char (&)[7], int&&}; long unsigned int ...I1 = {0ul}; long unsigned int ...I2 = {0ul, 1ul}; long unsigned int ...I3 = {0ul, 1ul}]’
A(std::tuple<T1...> args1,
^
/tmp/from_tuple.cpp:42:53: error: use of deleted function ‘constexpr std::tuple<_T1, _T2>::tuple(const std::tuple<_T1, _T2>&) [with _T1 = const char (&)[7]; _T2 = int&&]’
std::make_index_sequence<sizeof...(T3)>{} }
^
In file included from /tmp/from_tuple.cpp:1:0:
/usr/include/c++/5/tuple:615:17: note: ‘constexpr std::tuple<_T1, _T2>::tuple(const std::tuple<_T1, _T2>&) [with _T1 = const char (&)[7]; _T2 = int&&]’ is implicitly deleted because the default definition would be ill-formed:
constexpr tuple(const tuple&) = default;
^
/usr/include/c++/5/tuple:615:17: error: use of deleted function ‘constexpr std::_Tuple_impl<_Idx, _Head, _Tail ...>::_Tuple_impl(const std::_Tuple_impl<_Idx, _Head, _Tail ...>&) [with long unsigned int _Idx = 0ul; _Head = const char (&)[7]; _Tail = {int&&}]’
/usr/include/c++/5/tuple:215:17: note: ‘constexpr std::_Tuple_impl<_Idx, _Head, _Tail ...>::_Tuple_impl(const std::_Tuple_impl<_Idx, _Head, _Tail ...>&) [with long unsigned int _Idx = 0ul; _Head = const char (&)[7]; _Tail = {int&&}]’ is implicitly deleted because the default definition would be ill-formed:
constexpr _Tuple_impl(const _Tuple_impl&) = default;
^
/usr/include/c++/5/tuple:215:17: error: use of deleted function ‘constexpr std::_Tuple_impl<_Idx, _Head>::_Tuple_impl(const std::_Tuple_impl<_Idx, _Head>&) [with long unsigned int _Idx = 1ul; _Head = int&&]’
/usr/include/c++/5/tuple:364:17: note: ‘constexpr std::_Tuple_impl<_Idx, _Head>::_Tuple_impl(const std::_Tuple_impl<_Idx, _Head>&) [with long unsigned int _Idx = 1ul; _Head = int&&]’ is implicitly deleted because the default definition would be ill-formed:
constexpr _Tuple_impl(const _Tuple_impl&) = default;
^
/usr/include/c++/5/tuple:364:17: error: use of deleted function ‘constexpr std::_Head_base<_Idx, _Head, false>::_Head_base(const std::_Head_base<_Idx, _Head, false>&) [with long unsigned int _Idx = 1ul; _Head = int&&]’
/usr/include/c++/5/tuple:110:17: note: ‘constexpr std::_Head_base<_Idx, _Head, false>::_Head_base(const std::_Head_base<_Idx, _Head, false>&) [with long unsigned int _Idx = 1ul; _Head = int&&]’ is implicitly deleted because the default definition would be ill-formed:
constexpr _Head_base(const _Head_base&) = default;
^
/usr/include/c++/5/tuple:110:17: error: copying non-static data member ‘int&& std::_Head_base<1ul, int&&, false>::_M_head_impl’ of rvalue reference type
/tmp/from_tuple.cpp:23:7: note: initializing argument 3 of ‘A::A(std::tuple<_Elements ...>, std::tuple<_Elements ...>, std::tuple<_Tail ...>, std::integer_sequence<long unsigned int, I1 ...>, std::integer_sequence<long unsigned int, I2 ...>, std::integer_sequence<long unsigned int, I3 ...>) [with T1 = {const char (&)[4]}; T2 = {int&&, char&&}; T3 = {const char (&)[7], int&&}; long unsigned int ...I1 = {0ul}; long unsigned int ...I2 = {0ul, 1ul}; long unsigned int ...I3 = {0ul, 1ul}]’
A(std::tuple<T1...> args1,
^
Whoops, it looks like I just needed a bit more patience looking at the error messages. If I'd just looked at the first one, it was telling me that std::tuple<int&&, char&&> has an implicitly deleted copy constructor, presumably because of the rvalue-reference members. So, if I change the overload taking dummy integer_sequence objects to take tuple references, then the example compiles.
But then, in the case of the second element, it looks like it's using the initializer_list constructor instead of the intended size_t, char constructor. Changing from brace-initializers to the old-style parenthesized initializers in the same overload fixed that.
So overall, replace that overload with:
template <typename... T1, typename... T2, typename... T3,
std::size_t... I1, std::size_t... I2, std::size_t... I3>
A(std::tuple<T1...>& args1,
std::tuple<T2...>& args2,
std::tuple<T3...>& args3,
std::integer_sequence<std::size_t, I1...>,
std::integer_sequence<std::size_t, I2...>,
std::integer_sequence<std::size_t, I3...>) :
m_a(std::forward<T1>(std::get<I1>(args1))...),
m_b(std::forward<T2>(std::get<I2>(args2))...),
m_c(std::forward<T3>(std::get<I3>(args3))...)
{ }
The purpose of the following code is to display the contents of a structure. It is based on this answer.
#include <iostream>
#include <boost/fusion/adapted/struct/adapt_struct.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/for_each.hpp>
#include <boost/mpl/for_each.hpp>
#include <boost/mpl/range_c.hpp>
#include <boost/bind.hpp>
struct Node {
int a = 4;
double b = 2.2;
};
BOOST_FUSION_ADAPT_STRUCT(Node, b)
struct print_visitor {
template <class Index, class C> void operator()(Index, C &c) {
std::cout << boost::fusion::extension::struct_member_name<
C, Index::value>::call() << "="
<< boost::fusion::at<Index>(c) << std::endl;
}
};
template <class C> void print_fields(C &c) {
typedef boost::mpl::range_c<
int, 0, boost::fusion::result_of::size<C>::type::value> range;
boost::mpl::for_each<range>(
boost::bind<void>(print_visitor(), _1, boost::ref(c)));
}
int main() {
Node n;
print_fields(n);
}
The compiler (gcc version 4.8.2) complains:
invalid use of incomplete type ‘struct boost::fusion::result_of::at<Node, mpl_::integral_c<int, 0> >’
typedef typename T::type type;
What is the reason and how can I resolve this?
Here is the complete output of the compiler:
-*- mode: compilation; default-directory: "~/SearchLib/AstarWithPolicies/temp/" -*-
Compilation started at Thu Dec 10 11:54:27
make -k
g++ -Wall -Wextra -Werror -std=c++11 -pedantic -I ~/boost_1_59_0 -I /usr/include/cairomm-1.0/ -I /usr/include/cairo/ -I /usr/include/sigc++-2.0/ -I /usr/lib/x86_64-linux-gnu/sigc++-2.0/include/ -I /usr/include/freetype2/ -g -c temp.cpp
In file included from /home/meir/boost_1_59_0/boost/utility/enable_if.hpp:15:0,
from /home/meir/boost_1_59_0/boost/fusion/support/tag_of.hpp:11,
from /home/meir/boost_1_59_0/boost/fusion/support/category_of.hpp:12,
from /home/meir/boost_1_59_0/boost/fusion/adapted/struct/detail/extension.hpp:14,
from /home/meir/boost_1_59_0/boost/fusion/adapted/struct/adapt_struct.hpp:27,
from temp.cpp:7:
/home/meir/boost_1_59_0/boost/core/enable_if.hpp: In instantiation of ‘struct boost::lazy_disable_if_c<false, boost::fusion::result_of::at<Node, mpl_::integral_c<int, 0> > >’:
/home/meir/boost_1_59_0/boost/core/enable_if.hpp:70:10: required from ‘struct boost::lazy_disable_if<boost::is_const<Node>, boost::fusion::result_of::at<Node, mpl_::integral_c<int, 0> > >’
/home/meir/boost_1_59_0/boost/fusion/sequence/intrinsic_fwd.hpp:102:5: required by substitution of ‘template<class N, class Sequence> constexpr typename boost::lazy_disable_if<boost::is_const<Sequence>, boost::fusion::result_of::at<Sequence, N> >::type boost::fusion::at(Sequence&) [with N = mpl_::integral_c<int, 0>; Sequence = Node]’
temp.cpp:26:48: required from ‘void print_visitor::operator()(Index, C&) [with Index = mpl_::integral_c<int, 0>; C = Node]’
/home/meir/boost_1_59_0/boost/bind/bind.hpp:315:34: required from ‘void boost::_bi::list2<A1, A2>::operator()(boost::_bi::type<void>, F&, A&, int) [with F = print_visitor; A = boost::_bi::list1<mpl_::integral_c<int, 0>&>; A1 = boost::arg<1>; A2 = boost::reference_wrapper<Node>]’
/home/meir/boost_1_59_0/boost/bind/bind.hpp:907:50: required from ‘boost::_bi::bind_t<R, F, L>::result_type boost::_bi::bind_t<R, F, L>::operator()(A1&&) [with A1 = mpl_::integral_c<int, 0>&; R = void; F = print_visitor; L = boost::_bi::list2<boost::arg<1>, boost::reference_wrapper<Node> >; boost::_bi::bind_t<R, F, L>::result_type = void]’
/home/meir/boost_1_59_0/boost/mpl/for_each.hpp:78:25: required from ‘static void boost::mpl::aux::for_each_impl<false>::execute(Iterator*, LastIterator*, TransformFunc*, F) [with Iterator = boost::mpl::r_iter<mpl_::integral_c<int, 0> >; LastIterator = boost::mpl::r_iter<mpl_::integral_c<int, 1> >; TransformFunc = boost::mpl::identity<mpl_::na>; F = boost::_bi::bind_t<void, print_visitor, boost::_bi::list2<boost::arg<1>, boost::reference_wrapper<Node> > >]’
/home/meir/boost_1_59_0/boost/mpl/for_each.hpp:105:97: required from ‘void boost::mpl::for_each(F, Sequence*, TransformOp*) [with Sequence = boost::mpl::range_c<int, 0, 1>; TransformOp = boost::mpl::identity<mpl_::na>; F = boost::_bi::bind_t<void, print_visitor, boost::_bi::list2<boost::arg<1>, boost::reference_wrapper<Node> > >]’
/home/meir/boost_1_59_0/boost/mpl/for_each.hpp:118:48: required from ‘void boost::mpl::for_each(F, Sequence*) [with Sequence = boost::mpl::range_c<int, 0, 1>; F = boost::_bi::bind_t<void, print_visitor, boost::_bi::list2<boost::arg<1>, boost::reference_wrapper<Node> > >]’
temp.cpp:34:62: required from ‘void print_fields(C&) [with C = Node]’
temp.cpp:39:19: required from here
/home/meir/boost_1_59_0/boost/core/enable_if.hpp:63:30: error: invalid use of incomplete type ‘struct boost::fusion::result_of::at<Node, mpl_::integral_c<int, 0> >’
typedef typename T::type type;
^
In file included from /home/meir/boost_1_59_0/boost/fusion/sequence/intrinsic/begin.hpp:14:0,
from /home/meir/boost_1_59_0/boost/fusion/algorithm/iteration/detail/for_each.hpp:11,
from /home/meir/boost_1_59_0/boost/fusion/algorithm/iteration/for_each.hpp:12,
from /home/meir/boost_1_59_0/boost/fusion/include/for_each.hpp:11,
from temp.cpp:9:
/home/meir/boost_1_59_0/boost/fusion/sequence/intrinsic_fwd.hpp:53:16: error: declaration of ‘struct boost::fusion::result_of::at<Node, mpl_::integral_c<int, 0> >’
struct at;
^
temp.cpp: In instantiation of ‘void print_visitor::operator()(Index, C&) [with Index = mpl_::integral_c<int, 0>; C = Node]’:
/home/meir/boost_1_59_0/boost/bind/bind.hpp:315:34: required from ‘void boost::_bi::list2<A1, A2>::operator()(boost::_bi::type<void>, F&, A&, int) [with F = print_visitor; A = boost::_bi::list1<mpl_::integral_c<int, 0>&>; A1 = boost::arg<1>; A2 = boost::reference_wrapper<Node>]’
/home/meir/boost_1_59_0/boost/bind/bind.hpp:907:50: required from ‘boost::_bi::bind_t<R, F, L>::result_type boost::_bi::bind_t<R, F, L>::operator()(A1&&) [with A1 = mpl_::integral_c<int, 0>&; R = void; F = print_visitor; L = boost::_bi::list2<boost::arg<1>, boost::reference_wrapper<Node> >; boost::_bi::bind_t<R, F, L>::result_type = void]’
/home/meir/boost_1_59_0/boost/mpl/for_each.hpp:78:25: required from ‘static void boost::mpl::aux::for_each_impl<false>::execute(Iterator*, LastIterator*, TransformFunc*, F) [with Iterator = boost::mpl::r_iter<mpl_::integral_c<int, 0> >; LastIterator = boost::mpl::r_iter<mpl_::integral_c<int, 1> >; TransformFunc = boost::mpl::identity<mpl_::na>; F = boost::_bi::bind_t<void, print_visitor, boost::_bi::list2<boost::arg<1>, boost::reference_wrapper<Node> > >]’
/home/meir/boost_1_59_0/boost/mpl/for_each.hpp:105:97: required from ‘void boost::mpl::for_each(F, Sequence*, TransformOp*) [with Sequence = boost::mpl::range_c<int, 0, 1>; TransformOp = boost::mpl::identity<mpl_::na>; F = boost::_bi::bind_t<void, print_visitor, boost::_bi::list2<boost::arg<1>, boost::reference_wrapper<Node> > >]’
/home/meir/boost_1_59_0/boost/mpl/for_each.hpp:118:48: required from ‘void boost::mpl::for_each(F, Sequence*) [with Sequence = boost::mpl::range_c<int, 0, 1>; F = boost::_bi::bind_t<void, print_visitor, boost::_bi::list2<boost::arg<1>, boost::reference_wrapper<Node> > >]’
temp.cpp:34:62: required from ‘void print_fields(C&) [with C = Node]’
temp.cpp:39:19: required from here
temp.cpp:26:48: error: no matching function for call to ‘at(Node&)’
<< boost::fusion::at<Index>(c) << std::endl;
^
temp.cpp:26:48: note: candidates are:
In file included from /home/meir/boost_1_59_0/boost/fusion/sequence/intrinsic/begin.hpp:14:0,
from /home/meir/boost_1_59_0/boost/fusion/algorithm/iteration/detail/for_each.hpp:11,
from /home/meir/boost_1_59_0/boost/fusion/algorithm/iteration/for_each.hpp:12,
from /home/meir/boost_1_59_0/boost/fusion/include/for_each.hpp:11,
from temp.cpp:9:
/home/meir/boost_1_59_0/boost/fusion/sequence/intrinsic_fwd.hpp:102:5: note: template<class N, class Sequence> constexpr typename boost::lazy_disable_if<boost::is_const<Sequence>, boost::fusion::result_of::at<Sequence, N> >::type boost::fusion::at(Sequence&)
at(Sequence& seq);
^
/home/meir/boost_1_59_0/boost/fusion/sequence/intrinsic_fwd.hpp:102:5: note: substitution of deduced template arguments resulted in errors seen above
/home/meir/boost_1_59_0/boost/fusion/sequence/intrinsic_fwd.hpp:107:5: note: template<class N, class Sequence> constexpr typename boost::fusion::result_of::at<const Sequence, N>::type boost::fusion::at(const Sequence&)
at(Sequence const& seq);
^
/home/meir/boost_1_59_0/boost/fusion/sequence/intrinsic_fwd.hpp:107:5: note: template argument deduction/substitution failed:
/home/meir/boost_1_59_0/boost/fusion/sequence/intrinsic_fwd.hpp: In substitution of ‘template<class N, class Sequence> constexpr typename boost::fusion::result_of::at<const Sequence, N>::type boost::fusion::at(const Sequence&) [with N = mpl_::integral_c<int, 0>; Sequence = Node]’:
temp.cpp:26:48: required from ‘void print_visitor::operator()(Index, C&) [with Index = mpl_::integral_c<int, 0>; C = Node]’
/home/meir/boost_1_59_0/boost/bind/bind.hpp:315:34: required from ‘void boost::_bi::list2<A1, A2>::operator()(boost::_bi::type<void>, F&, A&, int) [with F = print_visitor; A = boost::_bi::list1<mpl_::integral_c<int, 0>&>; A1 = boost::arg<1>; A2 = boost::reference_wrapper<Node>]’
/home/meir/boost_1_59_0/boost/bind/bind.hpp:907:50: required from ‘boost::_bi::bind_t<R, F, L>::result_type boost::_bi::bind_t<R, F, L>::operator()(A1&&) [with A1 = mpl_::integral_c<int, 0>&; R = void; F = print_visitor; L = boost::_bi::list2<boost::arg<1>, boost::reference_wrapper<Node> >; boost::_bi::bind_t<R, F, L>::result_type = void]’
/home/meir/boost_1_59_0/boost/mpl/for_each.hpp:78:25: required from ‘static void boost::mpl::aux::for_each_impl<false>::execute(Iterator*, LastIterator*, TransformFunc*, F) [with Iterator = boost::mpl::r_iter<mpl_::integral_c<int, 0> >; LastIterator = boost::mpl::r_iter<mpl_::integral_c<int, 1> >; TransformFunc = boost::mpl::identity<mpl_::na>; F = boost::_bi::bind_t<void, print_visitor, boost::_bi::list2<boost::arg<1>, boost::reference_wrapper<Node> > >]’
/home/meir/boost_1_59_0/boost/mpl/for_each.hpp:105:97: required from ‘void boost::mpl::for_each(F, Sequence*, TransformOp*) [with Sequence = boost::mpl::range_c<int, 0, 1>; TransformOp = boost::mpl::identity<mpl_::na>; F = boost::_bi::bind_t<void, print_visitor, boost::_bi::list2<boost::arg<1>, boost::reference_wrapper<Node> > >]’
/home/meir/boost_1_59_0/boost/mpl/for_each.hpp:118:48: required from ‘void boost::mpl::for_each(F, Sequence*) [with Sequence = boost::mpl::range_c<int, 0, 1>; F = boost::_bi::bind_t<void, print_visitor, boost::_bi::list2<boost::arg<1>, boost::reference_wrapper<Node> > >]’
temp.cpp:34:62: required from ‘void print_fields(C&) [with C = Node]’
temp.cpp:39:19: required from here
/home/meir/boost_1_59_0/boost/fusion/sequence/intrinsic_fwd.hpp:107:5: error: invalid use of incomplete type ‘struct boost::fusion::result_of::at<const Node, mpl_::integral_c<int, 0> >’
/home/meir/boost_1_59_0/boost/fusion/sequence/intrinsic_fwd.hpp:53:16: error: declaration of ‘struct boost::fusion::result_of::at<const Node, mpl_::integral_c<int, 0> >’
struct at;
^
make: *** [all] Error 1
Compilation exited abnormally with code 2 at Thu Dec 10 11:54:27
I found this post as I'm practicing the use of the MPL. I got here as I wanted to print the struct_member_name which you were successful at. The short answer is to include <boost/fusion/sequence.hpp>. fusion::at requires a sequence
BOOST_FUSION_ADAPT_STRUCT does only that, it does not create a sequence for the target. If you had have accessed the value in the same way you access the name, it would have worked.
boost::fusion::extension::access::struct_member<C, Index::value>::template apply<C>::call(x)
returns the value of interest. But of course, there is always a better way, that much code is pretty ugly. Once you have a sequence applied to your class, everything gets easier. Now, I didn't find a for_each that iterates and passes types, fusion::for_each dereferences the value and passes that to the functor. So I took some code from boost\fusion\sequence\io\out.hpp which moves across an iterator range.
This example prints the data your way, the iterator way, and directly using fusion's IO. I'm sure I'm missing a whole lot, but this is my first day of actually writing compile time code that works. Thanks for your question, I may not have gotten so far without it!
#include <iostream>
#include <boost/mpl/range_c.hpp>
#include <boost/mpl/for_each.hpp>
#include <boost/fusion/sequence.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
//https://www.boost.org/doc/libs/1_78_0/libs/fusion/doc/html/fusion/support/deduce_sequence.html
#include <boost/bind/bind.hpp>
#include <boost/fusion/iterator/distance.hpp>
struct test {
int val;
std::string name;
};
BOOST_FUSION_ADAPT_STRUCT(test,val,name)
//the origanal with changes
struct print_class
{
template <class Index, typename T>
void operator()(Index, T& x) const
{
std::cout << "from print_class: " << boost::fusion::extension::struct_member_name<T, Index::value>::call()
<< " = " << boost::fusion::at<Index>(x) << std::endl;
}
};
using namespace boost::placeholders;
template <class C> void print_fields(C& c) {
typedef boost::mpl::range_c<
int, 0, boost::fusion::result_of::size<C>::type::value> range;
boost::mpl::for_each<range>(
boost::bind<void>(print_class(), _1, boost::ref(c)));
}
//I could not find anything like this in the fusion namespace, so...
//T is a fusion iterator
namespace boost::fusion {
template <typename T>
auto get_name(){return boost::fusion::extension::struct_member_name<T::seq_type, T::index::value>::call();
}
}
//shamelessly stolen from fusion/io....
namespace {
using namespace boost;
namespace bf = fusion;
struct print_sequence_loop
{
template <typename OS, typename First, typename Last>
static void call(OS&, First&, Last&, mpl::true_)
{
}
template <typename OS, typename First, typename Last>
static void call(OS& os, First& first, Last& last, mpl::false_)
{
bf::result_of::equal_to<
typename bf::result_of::next<First>::type
, Last
>is_last;
//The code that prints
os << bf::get_name<First>() << " = ";
os << *first << std::endl;
//End the code that prints
call(os, fusion::next(first), last, is_last);
}
template <typename OS, typename First, typename Last>
static void call(OS& os, First const& first, Last const& last)
{
bf::result_of::equal_to<First, Last> eq;
call(os, first, last, eq);
}
};
template <typename OS, typename Sequence>
inline void print_sequence(OS& os, Sequence& seq)
{
print_sequence_loop::call(os, fusion::begin(seq), fusion::end(seq));
}
}
using boost::fusion::operators::operator<<;
int main() {
test the_test{ 12,"this is me" };
print_sequence(std::cout, the_test);
std::cout << '\n';
print_fields(the_test);
std::cout << "\n\n this is using fusions OS\n";
std::cout << the_test << std::endl;
}
GCC demo And it works with MSVC.
Why does one variant assignment compile while the other does not? The template instances do not share any types and char could be converted to int, say. What is boost::variant trying to do, that it cannot do in the case of the first assignment and that it can do in the case of the second assignment? Error is below.
#include <string>
#include "boost/variant.hpp"
int main()
{
boost::variant<char> v1;
boost::variant<std::string, int, double> v2;
v1 = v2; // compile error
v2 = v1; // compiles fine
return 0;
}
In file included from /usr/include/boost/variant.hpp:17:0,
from v.cpp:3:
/usr/include/boost/variant/variant.hpp: In instantiation of 'int boost::variant<T0, TN>::convert_copy_into::internal_visit(T&, int) const [with T = const std::basic_string<char>; T0_ = char; TN = {}]':
/usr/include/boost/variant/detail/visitation_impl.hpp:113:9: required from 'typename Visitor::result_type boost::detail::variant::visitation_impl_invoke_impl(int, Visitor&, VoidPtrCV, T*, mpl_::true_) [with Visitor = boost::variant<char>::convert_copy_into; VoidPtrCV = const void*; T = std::basic_string<char>; typename Visitor::result_type = int; mpl_::true_ = mpl_::bool_<true>]'
/usr/include/boost/variant/detail/visitation_impl.hpp:156:9: required from 'typename Visitor::result_type boost::detail::variant::visitation_impl_invoke(int, Visitor&, VoidPtrCV, T*, NoBackupFlag, int) [with Visitor = boost::variant<char>::convert_copy_into; VoidPtrCV = const void*; T = std::basic_string<char>; NoBackupFlag = boost::variant<std::basic_string<char>, int, double>::has_fallback_type_; typename Visitor::result_type = int]'
/usr/include/boost/variant/detail/visitation_impl.hpp:237:5: required from 'typename Visitor::result_type boost::detail::variant::visitation_impl(int, int, Visitor&, VoidPtrCV, mpl_::false_, NoBackupFlag, Which*, step0*) [with Which = mpl_::int_<0>; step0 = boost::detail::variant::visitation_impl_step<boost::mpl::l_iter<boost::mpl::l_item<mpl_::long_<3l>, std::basic_string<char>, boost::mpl::l_item<mpl_::long_<2l>, int, boost::mpl::l_item<mpl_::long_<1l>, double, boost::mpl::l_end> > > >, boost::mpl::l_iter<boost::mpl::l_end> >; Visitor = boost::variant<char>::convert_copy_into; VoidPtrCV = const void*; NoBackupFlag = boost::variant<std::basic_string<char>, int, double>::has_fallback_type_; typename Visitor::result_type = int; mpl_::false_ = mpl_::bool_<false>]'
/usr/include/boost/variant/variant.hpp:2245:13: required from 'static typename Visitor::result_type boost::variant<T0, TN>::internal_apply_visitor_impl(int, int, Visitor&, VoidPtrCV) [with Visitor = boost::variant<char>::convert_copy_into; VoidPtrCV = const void*; T0_ = std::basic_string<char>; TN = {int, double}; typename Visitor::result_type = int]'
/usr/include/boost/variant/variant.hpp:2267:13: [ skipping 2 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
/usr/include/boost/variant/variant.hpp:1581:13: required from 'void boost::variant<T0, TN>::convert_construct_variant(Variant&) [with Variant = const boost::variant<std::basic_string<char>, int, double>; T0_ = char; TN = {}]'
/usr/include/boost/variant/variant.hpp:1628:42: required from 'void boost::variant<T0, TN>::convert_construct(const boost::variant<U0, UN ...>&, long int) [with U0 = std::basic_string<char>; UN = {int, double}; T0_ = char; TN = {}]'
/usr/include/boost/variant/variant.hpp:1649:38: required from 'boost::variant<T0, TN>::variant(const T&) [with T = boost::variant<std::basic_string<char>, int, double>; T0_ = char; TN = {}]'
/usr/include/boost/variant/variant.hpp:2059:29: required from 'void boost::variant<T0, TN>::assign(const T&) [with T = boost::variant<std::basic_string<char>, int, double>; T0_ = char; TN = {}]'
/usr/include/boost/variant/variant.hpp:2099:19: required from 'boost::variant<T0, TN>& boost::variant<T0, TN>::operator=(const T&) [with T = boost::variant<std::basic_string<char>, int, double>; T0_ = char; TN = {}]'
v.cpp:10:6: required from here
/usr/include/boost/variant/variant.hpp:1366:61: error: no matching function for call to 'boost::variant<char>::initializer::initialize(void* const&, const std::basic_string<char>&)'
return initializer::initialize(storage_, operand);
^
/usr/include/boost/variant/variant.hpp:1366:61: note: candidates are:
In file included from /usr/include/boost/variant/variant.hpp:32:0,
from /usr/include/boost/variant.hpp:17,
from v.cpp:3:
/usr/include/boost/variant/detail/initializer.hpp:104:24: note: static int boost::detail::variant::make_initializer_node::apply<BaseIndexPair, Iterator>::initializer_node::initialize(void*, boost::detail::variant::make_initializer_node::apply<BaseIndexPair, Iterator>::initializer_node::param_T) [with BaseIndexPair = boost::mpl::pair<boost::detail::variant::initializer_root, mpl_::int_<0> >; Iterator = boost::mpl::l_iter<boost::mpl::list1<char> >; boost::detail::variant::make_initializer_node::apply<BaseIndexPair, Iterator>::initializer_node::param_T = const char&]
static int initialize(void* dest, param_T operand)
^
/usr/include/boost/variant/detail/initializer.hpp:104:24: note: no known conversion for argument 2 from 'const std::basic_string<char>' to 'boost::detail::variant::make_initializer_node::apply<boost::mpl::pair<boost::detail::variant::initializer_root, mpl_::int_<0> >, boost::mpl::l_iter<boost::mpl::list1<char> > >::initializer_node::param_T {aka const char&}'
/usr/include/boost/variant/detail/initializer.hpp:115:24: note: static int boost::detail::variant::make_initializer_node::apply<BaseIndexPair, Iterator>::initializer_node::initialize(void*, boost::detail::variant::make_initializer_node::apply<BaseIndexPair, Iterator>::initializer_node::param2_T) [with BaseIndexPair = boost::mpl::pair<boost::detail::variant::initializer_root, mpl_::int_<0> >; Iterator = boost::mpl::l_iter<boost::mpl::list1<char> >; boost::detail::variant::make_initializer_node::apply<BaseIndexPair, Iterator>::initializer_node::param2_T = char&&]
static int initialize(void* dest, param2_T operand)
^
/usr/include/boost/variant/detail/initializer.hpp:115:24: note: no known conversion for argument 2 from 'const std::basic_string<char>' to 'boost::detail::variant::make_initializer_node::apply<boost::mpl::pair<boost::detail::variant::initializer_root, mpl_::int_<0> >, boost::mpl::l_iter<boost::mpl::list1<char> > >::initializer_node::param2_T {aka char&&}'
/usr/include/boost/variant/detail/initializer.hpp:149:17: note: static void boost::detail::variant::initializer_root::initialize()
static void initialize();
^
/usr/include/boost/variant/detail/initializer.hpp:149:17: note: candidate expects 0 arguments, 2 provided
A char definitely can be stored in an int but the converse is not always true. Therefore the one that fails to compile would be unsafe at runtime, so you're probably better off with it failing. Cast the int to a char if you must.
The purpose is to execute CVS890Executor::do_full_frame when calling the m_callback_fn within CDevVS890.
Following is the incriminated code:
"CDevVS890.h"
typedef std::tr1::function<void (void* frame, int len)> DoFrameFn;
class CDevVS890
{
public:
CDevVS890();
void receive();
DoFrameFn m_callback_fn;
}
"CDevVS890.cpp"
void CDevVS890::receive()
{
...
m_callback_fn((void*)frame, (int)len);
}
/*----------------------------------------------------------------------*/
"CVS890Executor.h"
class CVS890Executor
{
public:
CVS890Executor();
private:
void hookup_to_DevVS890();
void do_full_frame( void* frame, int len );
}
"CVS890Executor.cpp"
CVS890Executor::CVS890Executor()
{
hookup_to_DevVS890();
}
void CVS890Executor::hookup_to_DevVS890()
{
m_pDevVS890 = new CDevVS890();
m_pDevVS890->m_callback_fn =
std::tr1::bind(&CVS890Executor::do_full_frame, this, _1);
}
void CVS890Executor::do_full_frame(void* frame, int len)
{
...
}
The errors are multiple and very difficult to read:
In file included from /usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/tr1/functional:56,
from ../../src/Common/CDevVS890.h:17,
from CVS890Executor.h:13,
from CVS890Executor.cpp:8:
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/tr1_impl/functional: In member function âtypename std::tr1::result_of<_Functor(typename std::tr1::result_of 0)>(_Bound_args, std::tr1::tuple<_UElements ...>)>::type ...)>::type std::tr1::_Bind<_Functor(_Bound_args ...)>::__call(const std::tr1::tuple<_UElements ...>&, std::tr1::_Index_tuple<_Indexes ...>) [with _Args = void*&, int&, int ..._Indexes = 0, 1, _Functor = std::tr1::_Mem_fn, _Bound_args = CVS890Executor*, std::tr1::_Placeholder<1>]â:
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/tr1_impl/functional:1191: instantiated from âtypename std::tr1::result_of<_Functor(typename std::tr1::result_of 0)>(_Bound_args, std::tr1::tuple<_UElements ...>)>::type ...)>::type std::tr1::_Bind<_Functor(_Bound_args ...)>::operator()(_Args& ...) [with _Args = void*, int, _Functor = std::tr1::_Mem_fn, _Bound_args = CVS890Executor*, std::tr1::_Placeholder<1>]â
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/tr1_impl/functional:1668: instantiated from âstatic void std::tr1::_Function_handler::_M_invoke(const std::tr1::_Any_data&, _ArgTypes ...) [with _Functor = std::tr1::_Bind(CVS890Executor*, std::tr1::_Placeholder<1>)>, _ArgTypes = void*, int]â
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/tr1_impl/functional:2005: instantiated from âstd::tr1::function<_Res(_ArgTypes ...)>::function(_Functor, typename __gnu_cxx::__enable_if<(! std::tr1::is_integral::value), std::tr1::function<_Res(_ArgTypes ...)>::Useless>::_type) [with _Functor = std::tr1::_Bind(CVS890Executor*, std::tr1::_Placeholder<1>)>, _Res = void, _ArgTypes = void*, int]â
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/tr1_impl/functional:1885: instantiated from âtypename __gnu_cxx::__enable_if<(! std::tr1::is_integral::value), std::tr1::function<_Res(ArgTypes ...)>&>::_type std::tr1::function<_Res(_ArgTypes ...)>::operator=(_Functor) [with _Functor = std::tr1::_Bind(CVS890Executor*, std::tr1::_Placeholder<1>)>, _Res = void, _ArgTypes = void*, int]â
CVS890Executor.cpp:115: instantiated from here
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/tr1_impl/functional:1137: error: no match for call to â(std::tr1::_Mem_fn) (CVS890Executor*&, void*&)â
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/tr1_impl/functional:546: note: candidates are: _Res std::tr1::_Mem_fn<_Res (_Class::*)(_ArgTypes ...)>::operator()(_Class&, _ArgTypes ...) const [with _Res = void, _Class = CVS890Executor, _ArgTypes = void*, int]
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/tr1_impl/functional:551: note: _Res std::tr1::_Mem_fn<_Res (_Class::*)(_ArgTypes ...)>::operator()(_Class*, _ArgTypes ...) const [with _Res = void, _Class = CVS890Executor, _ArgTypes = void*, int]
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/tr1_impl/functional:1137: error: return-statement with a value, in function returning 'void'
make: * [CVS890Executor.o] Error 1
Any idea what's wrong with this?
Cheers
You forgot about the second argument. Your call of bind function should be like this:
std::tr1::bind(&CVS890Executor::do_full_frame, this, _1, _2);
// ^^
In CVS890Executor::hookup_to_DevVS890(), you are not binding any arguments to the member function do_full_frame.
You are also trying to assign the return value of the function to m_callback_fn but do_full_frame() is declared to return void (no return value).