I have this smart and cool example:
#include <iostream>
#include "boost/multi_array.hpp"
#include "boost/array.hpp"
#include "boost/cstdlib.hpp"
template <typename Array>
void print(std::ostream& os, const Array& A)
{
typename Array::const_iterator i;
os << "[";
for (i = A.begin(); i != A.end(); ++i) {
print(os, *i);
if (boost::next(i) != A.end())
os << ',';
}
os << "]";
}
void print(std::ostream& os, const double& x)
{
os << x;
}
int main()
{
typedef boost::multi_array<double, 2> array;
double values[] = {
0, 1, 2,
3, 4, 5
};
const int values_size=6;
array A(boost::extents[2][3]);
A.assign(values,values+values_size);
print(std::cout, A);
return boost::exit_success;
}
But if I try to compile it: g++ -I/usr/include/boost/ b.cpp I get this error:
b.cpp: In function ‘void print(std::ostream&, const Array&) [with Array = double]’:
b.cpp:12: instantiated from ‘void print(std::ostream&, const Array&) [with Array = boost::detail::multi_array::const_sub_array<double, 1u, const double*>]’
b.cpp:12: instantiated from ‘void print(std::ostream&, const Array&) [with Array = main()::array]’
b.cpp:32: instantiated from here
b.cpp:9: error: ‘double’ is not a class, struct, or union type
b.cpp:11: error: request for member ‘begin’ in ‘A’, which is of non-class type ‘const double’
b.cpp:9: error: ‘double’ is not a class, struct, or union type
b.cpp:9: error: request for member ‘end’ in ‘A’, which is of non-class type ‘const double’
b.cpp:9: error: ‘double’ is not a class, struct, or union type
b.cpp:9: error: ‘double’ is not a class, struct, or union type
b.cpp:9: error: ‘double’ is not a class, struct, or union type
b.cpp:13: error: request for member ‘end’ in ‘A’, which is of non-class type ‘const double’
b.cpp:9: error: ‘double’ is not a class, struct, or union type
shell returned 1
What was wrong? It seems to not understand the difference between the first and the second print function. Maybe some compiler options I missed?
EDIT:
If i use template<> as Craig H answer i resolve the problem in a isolated example.cpp. But if i put the 2 functions in a separate .h file in my project, the error appears again!
In this example you created a template function as your first print function then declare another function that implements a specific version of that template without template specializing. I think if you change the following line
void print(std::ostream& os, const double& x)
to
template<> void print<double>(std::ostream& os, const double& x)
your problem should go away.
Related
I'm trying to map string to function pointer, so that I can call the function with iter->second(arg) instead of if-else.
I have written a simple one without class, and it works as expected.
But when I modify it as below, it shows compile errors.
#include <functional>
#include <iostream>
#include <unordered_map>
#include <string>
using std::string;
class A{
private:
int a(int num, string s) { return s.size() + num; }
int b(int num, string s) { return num - s.size(); }
public:
void ido(string str){
typedef std::function<int(int, string)> process_func;
std::unordered_map<string, process_func> m;
m.insert(std::make_pair<string, process_func>("a", &A::a));
// using std::placeholders::_1;
// m.insert(std::make_pair<string, process_func>("a", std::bind(&A::a, this, _1)));
// m["a"] = std::bind(&A::a, this, _1);
// m.insert({{"a", &A::a}, {"b", &A::b}});
auto x = m.find(str);
if(x == m.end()) {
std::cout << "Not supported!" << std::endl;
}
std::cout << x->second(10, "hello") << std::endl;
}
};
int main(int argc, char* argv[]) {
A a;
a.ido(string(argv[1]));
return 0;
}
The errors are:
function.cc: In member function ‘void A::ido(std::string)’:
function.cc:17:65: error: no matching function for call to ‘make_pair(const char [2], int (A::*)(int, std::string))’
m.insert(std::make_pair<string, process_func>("a", &A::a));
^
function.cc:17:65: note: candidate is:
In file included from /usr/include/c++/4.8.2/utility:70:0,
from /usr/include/c++/4.8.2/tuple:38,
from /usr/include/c++/4.8.2/functional:55,
from function.cc:1:
/usr/include/c++/4.8.2/bits/stl_pair.h:276:5: note: template<class _T1, class _T2> constexpr std::pair<typename std::__decay_and_strip<_Tp>::__type, typename std::__decay_and_strip<_T2>::__type> std::make_pair(_T1&&, _T2&&)
make_pair(_T1&& __x, _T2&& __y)
^
/usr/include/c++/4.8.2/bits/stl_pair.h:276:5: note: template argument deduction/substitution failed:
function.cc:17:65: note: cannot convert ‘&A::a’ (type ‘int (A::*)(int, std::string) {aka int (A::*)(int, std::basic_string<char>)}’) to type ‘std::function<int(int, std::basic_string<char>)>&&’
m.insert(std::make_pair<string, process_func>("a", &A::a));
What does the error mean? How to fix it?
While your functions 'a' and 'b' do not depend on 'this' (they do not access anything inside class A), the compiler is not smart enough to deduce this. So the error means that you are trying to convert 'pointer to method' to 'pointer to function', which is incorrect conversion. 'Pointer to method' requires and object to be called on. You need to declare methods 'a' and 'b' as 'static' to indicate that they are actually standalone functions, not methods of the class.
I am trying construct a constexpr union which wraps 3 types. The union can contain a raw uint8_t array or fixed length arrays of PODTypeA or PODTypeB. The lengths of these arrays are known at compile time and given by constexpr values.
The POD structures are very simple:
struct PODTypeA {
int a;
int b;
};
or
struct PODTypeB {
uint32_t a;
uint32_t b;
};
The embedded environment does not have the standard template library available. As such, I cannot use the constexpr std::array<T,N> which would make things a lot easier.
Shown below is a constexpr Array(const Args&... args) array implementation, which should function as a constexpr data member to hold array fields.
template <typename T, std::size_t Size>
struct Array {
T data[Size];
template <typename ...Args>
constexpr Array(const Args&... args)
: data{ args... }
{}
};
I don't fully understand how the parameter pack expansion works (effectively memcpy(ing) the array via the compiler to the specified union member). If someone could explain that it would be a plus. I found the above Array template parameter pack expander in the checked answer to the following stack overlflow question (where there is also a live example).
I put this in a coliru project but I am having lots of compile issues.
I have 3 constructors for the union, each one of these takes a fixed length array parameter as follows:
constexpr static auto gSizeBytes = 2048;
constexpr static int gArraySizeA = 2;
constexpr static int gArraySizeB = 3;
union UnionStruct {
explicit constexpr UnionStruct(
const uint8_t(&rParam)[gSizeBytes] = {})
: byteArray(rParam)
{}
explicit constexpr UnionStruct(
const PODTypeA(&rParam)[gArraySizeA])
: arrayA(rParam)
{}
explicit constexpr UnionStruct(
const PODTypeB(&rParam)[gArraySizeB])
: arrayB(rParam)
{}
Array<uint8_t, gSizeBytes> byteArray;
Array<PODTypeA, gArraySizeA> arrayA;
Array<PODTypeB, gArraySizeB> arrayB;
};
And here is how I expect to use it:
int main()
{
PODTypeA[UnionStruct::gArraySizeA] arrayTypeA = {{1,2}, {3,4}};
// construct union from fixed PODTypeA array with 2 elements
UnionStruct foo (arrayTypeA);
}
The compiler issues the following errors:
g++ -std=c++17 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
main.cpp: In instantiation of 'constexpr Array<T, Size>::Array(const Args& ...) [with Args = {unsigned char [2048]}; T = unsigned char; long unsigned int Size = 2048]':
main.cpp:34:27: required from here
main.cpp:12:25: error: invalid conversion from 'const unsigned char*' to 'unsigned char' [-fpermissive]
: data{ args... }
^
main.cpp: In instantiation of 'constexpr Array<T, Size>::Array(const Args& ...) [with Args = {PODTypeA [2]}; T = PODTypeA; long unsigned int Size = 2]':
main.cpp:39:24: required from here
main.cpp:12:25: error: invalid conversion from 'const PODTypeA*' to 'int' [-fpermissive]
main.cpp: In instantiation of 'constexpr Array<T, Size>::Array(const Args& ...) [with Args = {PODTypeB [3]}; T = PODTypeB; long unsigned int Size = 3]':
main.cpp:44:24: required from here
main.cpp:12:25: error: invalid conversion from 'const PODTypeB*' to 'uint32_t' {aka 'unsigned int'} [-fpermissive]
main.cpp: In function 'int main()':
main.cpp:54:14: error: expected identifier before numeric constant
PODTypeA[2] arrayTypeA = {{1,2}, {3,4}};
^
main.cpp:54:14: error: expected ']' before numeric constant
PODTypeA[2] arrayTypeA = {{1,2}, {3,4}};
^
]
main.cpp:54:13: error: structured binding declaration cannot have type 'PODTypeA'
PODTypeA[2] arrayTypeA = {{1,2}, {3,4}};
^
main.cpp:54:13: note: type must be cv-qualified 'auto' or reference to cv-qualified 'auto'
main.cpp:54:13: error: empty structured binding declaration
main.cpp:54:17: error: expected initializer before 'arrayTypeA'
PODTypeA[2] arrayTypeA = {{1,2}, {3,4}};
^~~~~~~~~~
main.cpp:56:22: error: 'arrayTypeA' was not declared in this scope
UnionStruct foo (arrayTypeA);
^~~~~~~~~~
main.cpp:56:22: note: suggested alternative: 'gArraySizeA'
UnionStruct foo (arrayTypeA);
^~~~~~~~~~
gArraySizeA
main.cpp:54:13: warning: unused structured binding declaration [-Wunused-variable]
PODTypeA[2] arrayTypeA = {{1,2}, {3,4}};
^
I want to use Boost phoenix member function operator for the class function that has overloads, like here.
The following example fails:
#include <boost/phoenix/phoenix.hpp>
#include <boost/phoenix/operator.hpp>
using namespace std;
using namespace boost::phoenix::placeholders;
struct A
{
int m_id = 1;
int func() const { return 1; }
void func(int id) { m_id = id; }
};
int main()
{
A *a = new A;
auto retVal = (arg1->*&A::func)()(a);
return 0;
}
With error:
In function 'int main()': 17:21: error: no match for 'operator->*'
(operand types are 'const type {aka const
boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::proto::tagns_::
tag::terminal, boost::proto::argsns_::term<boost::phoenix::argument<1> >, 0l>
>}' and '<unresolved overloaded function type>') 17:21: note: candidate is: In
file included from /usr/include/boost/phoenix/operator/arithmetic.hpp:13:0,
from /usr/include/boost/phoenix/operator.hpp:13, from /usr/include/boost
/phoenix/phoenix.hpp:13, from 1: /usr/include/boost/proto/operators.hpp:295:9:
note: template<class Left, class Right> const typename
boost::proto::detail::enable_binary<boost::proto::domainns_::deduce_domain,
boost::proto::detail::not_a_grammar,
boost::mpl::or_<boost::proto::is_extension<Arg>,
boost::proto::is_extension<Right> >, boost::proto::tagns_::tag::mem_ptr, const
Left&, const Right&>::type boost::proto::exprns_::operator->*(Left&&,
Right&&) BOOST_PROTO_DEFINE_OPERATORS(is_extension, deduce_domain) ^
/usr/include/boost/proto/operators.hpp:295:9: note: template argument
deduction/substitution failed: 17:28: note: couldn't deduce template parameter
'Right'
However, if I comment the line void func(int id) { m_id = id; } out, it works as expected.
How can I tell which of the overloads to use?
Handling (member) function pointers to overload sets is always a pain. You need to cast the address to a pointer that has the exact signature of the desired overload. In your case, for selection int A::func():
auto retVal = (arg1->*static_cast<int (A::*)() const>(&A::func))()(a);
or a bit more readable, but basically the same:
const auto memFctPtr = static_cast<int (A::*)() const>(&A::func);
auto retVal = (arg1->*memFctPtr)()(a);
I have the following code:
#include <memory>
int main()
{
int* a = new int(2);
std::unique_ptr<decltype(*a)> p(a);
}
which leads to these error message:
In file included from a.cpp:1:
In file included from /usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/memory:81:
/usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/bits/unique_ptr.h:138:14: error: '__test' declared as a pointer to a reference of type 'int &'
static _Tp* __test(...);
^
/usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/bits/unique_ptr.h:146:35: note: in instantiation of member class 'std::unique_ptr<int &,
std::default_delete<int &> >::_Pointer' requested here
typedef std::tuple<typename _Pointer::type, _Dp> __tuple_type;
^
a.cpp:7:35: note: in instantiation of template class 'std::unique_ptr<int &, std::default_delete<int &> >' requested here
std::unique_ptr<decltype(*a)> p(a);
^
In file included from a.cpp:1:
In file included from /usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/memory:81:
/usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/bits/unique_ptr.h:227:33: error: 'type name' declared as a pointer to a reference of type 'int &'
is_convertible<_Up*, _Tp*>, is_same<_Dp, default_delete<_Tp>>>>
^
a.cpp:7:35: note: in instantiation of template class 'std::unique_ptr<int &, std::default_delete<int &> >' requested here
std::unique_ptr<decltype(*a)> p(a);
^
2 errors generated.
I understand the reason is that the unique_ptr template expects type int, but decltype(*a) gives int&. In the case that int is a very long and complicated type, how can I make this code work with decltype?
Use std::decay_t. This is the conversion that is applied when you pass an argument to a function by value.
You can use a typedef inside a templated class and then use template specialisation, like this
template<typename T> struct unref {
typedef T raw;
};
template<typename T> struct unref<T&> {
typedef T raw;
};
int main() {
int* a = new int(2);
std::unique_ptr<unref<decltype(*a)>::raw> p(a);
}
I'm using gcc 4.3.2.
I have the following code (simplified):
#include <cstdlib>
template<int SIZE>
class Buffer
{
public:
explicit Buffer(const char *p = NULL) {}
explicit Buffer(const Buffer &other);
const char *c_str() const { return m_buffer; }
private:
char m_buffer[SIZE];
};
typedef Buffer<10> A;
typedef Buffer<20> B;
void Foo(A a) {
}
int main()
{
B b;
Foo(b.c_str()); // line 25 fails compilation
return 1;
}
Compilation yields:
test.cpp: In function ‘int main()’:
test.cpp:25: error: conversion from ‘const char*’ to non-scalar type ‘A’ requested
But there's c-tor receiving const char *.
UDP:
If I remove explicit from 1st c-tor I receive
test.cpp: In function ‘int main()’:
test.cpp:25: error: no matching function for call to ‘Buffer<10>::Buffer(A)’
test.cpp:7: note: candidates are: Buffer<SIZE>::Buffer(const char*) [with int SIZE = 10]
test.cpp:25: error: initializing argument 1 of ‘void Foo(A)’
If I use Foo(A(b.c_str())) I receive:
test.cpp: In function ‘int main()’:
test.cpp:25: error: no matching function for call to ‘Buffer<10>::Buffer(A)’
test.cpp:25: error: initializing argument 1 of ‘void Foo(A)’
Your conversion constructor is declared explicit. Keyword explicit is specifically intended to prevent implicit conversions by that constructor. And an implicit conversion is exactly what you expect to happen in your code (at the Foo call).
Why did you declare your constructor explicit, if you want it to work in implicit conversions?
A and B are totally different types. As Andrey pointed out, there is no implicit callable constructor for conversion. You'll have to write
Foo(A(b.c_str()));
This will create a temporary 'automatic' (unnamed) object of type A using the explicit constructor for const char. And this will be passed to Foo.