I was trying to define a generic operator for containers as follows:
#include <algorithm>
#include <functional>
namespace test {
template<template <typename...> class _Container,
typename _Type, typename... _Args>
_Container<_Type,_Args...>
operator+(const _Container<_Type,_Args...>& c1,
const _Container<_Type,_Args...>& c2)
{
typedef _Container<_Type,_Args...> container_type;
assert(c1.size() == c2.size());
container_type result;
std::transform(c1.begin(), c1.end(), c2.begin(),
std::back_inserter(result), std::plus<_Type>());
return result;
}
} // test namespace
However, GCC 4.9.2 does not try as a candidate for the following test code:
typedef std::vector<int> vector;
vector v1, v2;
vector result = v1 + v2;
I also tried the above without the parameter pack for the template. Same result.
However, without the namespace declaration, it works fine.
What am I doing wrong? Similar operators defined by the STL in the std namespace are tested as candidates.
The error message is simply:
/tmp/file.cc: In function ‘int main()’:
/tmp/file.cc:28:22: error: no match for ‘operator+’ (operand types are ‘vector {aka std::vector<int>}’ and ‘vector {aka std::vector<int>}’)
I was trying to define a generic operator for containers
uh oh...
Ignoring the ADL issues you will have, there are semantic issues too.
For example, consider:
vector<int> a { 1, 2, 3 };
vector<int> b { 4, 5, 6 };
auto c = a + b; // this won't compile, it's for illustration.
Question: What should the operation do?
Some people might think it should model this:
auto c = concatenate(a, b);
// c == { 1, 2, 3, 4, 5, 6 }
Others might think it should do as you suggest:
auto c = add_elements(a, b);
// c == { 5, 7, 9 }
Who's right?
The answer is that it depends on the context of use of the vector. The vector is a primitive type. It carries no information about the use case. There is simply not enough information available to make an informed choice.
Wrapping the vector into a custom type allows you to provide contextual information and describe the actions of operators correctly.
Of course, you will need to define the arithmetic operators explicitly for the type.
In summary:
The standard library does not define arithmetic operators for containers for good reason. For that same reason, neither should you.
As a parting note, even the transform interpretation is not trivial. What should happen if the vectors are of different size?
Related
I have defined a vector of the boundary_info structure as std::vector<boundary_info> nodes to be used in my code for a specific purpose. While I try to push_back new elements into this vector in a specific function as:
void myFun()
{
std::vector<float_type> dists(9, -1.0);
std::array<float_type,9> f, g;
//do something - x and y are defined here
nodes.push_back(boundary_info{point<int>{x,y}, dists, f, g, {}});
}
I get the following error message :
Error 1 : cannot convert ‘std::vector<float>’ to ‘float’ in initialization
Error 2 : cannot convert ‘std::array<float, 9ul>’ to ‘float’ in
initialization
Error 3 : cannot convert ‘std::array<float, 9ul>’ to ‘float’ in
initialization
Error 1 is associated with dists, which is a vector. Errors 2 and 3 are associated with the f, g passed as parameters in push_back respectively.
The code is shown below.
#include <iostream>
#include <vector>
template <typename T>
struct point //specify a point structure
{
T x,y;
};
struct boundary_info
{
point<int> xy_bdary; //coordinates of a bdary point
std::array<float_type,9> dist; //distance from boundary
std::array<float_type,9> f_prev, g_prev; //populations
std::vector<int> miss_dirns; //missing directions
};
I would be glad if the solution for this error would be pointed out. I have been struggling with it since half a day.
Note : I am compiling using c++11.
Edit
You can find a minimal code of this problem reproducing the same problem at
https://repl.it/repls/GleefulTartMarkuplanguage
Thanks
In the following line you are trying to initialize a std::array (boundary_info::dist) from a std::vector (dists):
nodes.push_back(boundary_info{point<int>{x,y}, dists, f, g, {}});
std::array doesn't have a constructor that accepts a std::vector. You could only initialize the std::array element-wise (aggregate initialization) or explicitly copy the std::vector to the std::array.
Aggregate initialization
nodes.push_back(boundary_info{point<int>{x,y}, {dists[0], dists[1], dists[2], dists[3], dists[4], dists[5], dists[6], dists[7], dists[8]}, f, g, {}});
Of course, that's not very elegant.
Copy std::vector to std::array
With the help of a little template function, we can do better.
template<typename T, std::size_t N, typename Range>
std::array<T,N> to_array( Range const& in )
{
std::array<T,N> result;
// To make the standard begin() and end() in addition to any user-defined
// overloads available for ADL.
using std::begin; using std::end;
std::copy( begin( in ), end( in ), result.begin() );
return result;
}
Live demo
to_array accepts any input type that has begin() and end() member functions or overloads of the free functions begin() and end().
Now you can initialize the array from the vector like this:
nodes.push_back(boundary_info{point<int>{x,y}, to_array<float_type,9>(dists), f, g, {}});
Note that you can easily shoot yourself in the foot if dists has more elements than the array, because to_array doesn't do any range checking (std::copy doesn't do either). I'll leave it as an exercise for the reader to make the function more secure, if needed.
I am trying to do a reduction based on eigen matrix.
#include <iostream>
#include <Eigen/Dense>
#include <type_traits>
template<typename T1, typename T2, int n1, int n2>
auto reduction(Eigen::Matrix<T1, n1, n2> &a1,
Eigen::Matrix<T2, n1, n2> &a2)
-> decltype(T1{}*T2{})
{
using BaseT3 =
typename std::remove_cv<typename std::remove_reference<decltype(T1{}*T2{})>::type>::type;
BaseT3 res = a1(0, 0)*a2(0, 0);
for (int i=0; i<n1; ++i)
for (int j=0; j<n2; ++j)
if (i+j)
res = res + a1(i, j)*a2(i, j);
return res;
}
int main()
{
Eigen::Matrix<double, 3, 3> m;
Eigen::Matrix<Eigen::Vector3d, 3, 3> n;
std::cout << reduction(m, n) << std::endl;
}
Basically, Im a trying to get sum_{i, j} a1[i, j] * a2[i, j] where a1 and a2 are some eigen mathix but I get compilation errors. The error I get is
error: no match for ‘operator=’ (operand types are ‘BaseT3 {aka
Eigen::CwiseUnaryOp<Eigen::internal::scalar_multiple_op<double>,
const Eigen::Matrix<double, 3, 1> >}’
and
‘const Eigen::CwiseBinaryOp<Eigen::internal::scalar_sum_op<double>,
const Eigen::CwiseUnaryOp<Eigen::internal::scalar_multiple_op<double>,
const Eigen::Matrix<double, 3, 1> >,
const Eigen::CwiseUnaryOp<Eigen::internal::scalar_multiple_op<double>,
const Eigen::Matrix<double, 3, 1> > >’)
res = res + a1(i, j)*a2(i, j);
^
If I am not mistaken, for the given main, type BaseT3 should have been Eigen::Vector3d. I also tried to static cast so the operator= should not fail but I then get other errors.
This is c++11, I use Eigen3 and the compiler is g++ 5.4.1.
The decltype of T1 * T2 isn't what you expect here - Eigen heavily uses expression templates. The CWiseUnaryOp and CWiseBinaryOp types in your error are indicative of that. In other words, the result of "double * Vector3d" isn't what you'd expect (it's not a Vector3d, it's a cwisebinaryop).
See also: Writing functions taking Eigen Types.
In this specific case you may find a solution by creating partial specializations for Eigen base types for both the first and second parameters of your template function.
Eigen uses expression templates to optimize chains of operations.
So MatrixA*MatrixB is not a Matrix type, but rather an expression that says "when evaluated this will be the product of a MatrixA times a MatrixB".
The result is that A*B+C*D doesn't create (at least as many) temporary matrixes, but instead when stored in an output matrix the results are "lazily" calculated directly into the output matrix.
Now, you are multipying elements. But one of your element types is in turn a matrix. And Eigen does expression template optimization of scalar times vector it turns out.
The type you want is std::decay_t<decltype((T1{}+T2{}).eval())> (well the C++11 verbose version of that).
You could write a fancy SFINAE thing that checks if it can be evaluated, and if so does that. Or you can test for Eigen expression template types.
I understand a set is ordered, thus adding an object without overloading the < operator doesn't allow to say which object is smaller to keep the container sorted. However, I don't understand why this isn't possible with an unordered_set.
If I try something like this:
#include <iostream>
#include <string
#include <unordered_set>
struct someType{
string name;
int code;
};
int main(){
std::unordered_set <someType> myset;
myset.insert({"aaa",123});
myset.insert({"bbb",321});
myset.insert({"ccc",213});
return 0;
}
I get a couple of errors like:
c:\qt\qt5.1.0\tools\mingw48_32\lib\gcc\i686-w64-mingw32\4.8.0\include\c++\bits\hashtable_policy.h:1070: error: invalid use of incomplete type 'struct std::hash'
c:\qt\qt5.1.0\tools\mingw48_32\lib\gcc\i686-w64-mingw32\4.8.0\include\c++\bits\functional_hash.h:58: error: declaration of 'struct std::hash'
error: no matching function for call to 'std::unordered_set::unordered_set()'
c:\qt\qt5.1.0\tools\mingw48_32\lib\gcc\i686-w64-mingw32\4.8.0\include\c++\bits\hashtable_policy.h:1103: error: no match for call to '(const std::hash) (const someType&)'
c:\qt\qt5.1.0\tools\mingw48_32\lib\gcc\i686-w64-mingw32\4.8.0\include\c++\bits\stl_function.h:208: error: no match for 'operator==' (operand types are 'const someType' and 'const someType')
Why is that and how can I fix it?
To use type in unordered_set or unordered_map you need hashing function for your type. For common types, like int or std::string - hashing function is provided by standard library. For your type, you can overload standard std::hash, like this:
namespace std {
template <> struct hash<someType> {
size_t operator()(const someType & x) const {
std::hash<std::string> h;
return h(x.name);
// or simply return x.code
// or do something more interesting,
// like xor'ing hashes from both members of struct
}
};
}
Another way is to provide your own type with overloaded operator() and put it as hash template argument in unordered_set, like this:
struct someTypeHasher {
size_t operator()(const someType& x) const {
return x.code;
}
};
std::unordered_set<someType, someTypeHasher> myset;
Good reading for theory about hash based containers is here
Also, do not forget, that you need to overload operator== for someType, without it - it will also not work.
As explained in the answer given by Starl1ght, you need to provide a hash function for someType. However, I would combine all members of your class by that hash function. Otherwise, you might get a lot of collisions, for example, if the same name occurs very often, but with different code values. For creating a hash function, you can make use of Boost, but you can also handcraft it.
Starl1ght also mentioned that you need to overload operator== for someType,
but you can also define a separate comparison function instead and provide it to the unordered_set. Moreover, you can use lambda expressions instead of defining the hash and comparison functions. If you put everything together, then your code could be written as follows:
auto hash = [](const someType& st){
return std::hash<std::string>()(st.name) * 31 + std::hash<int>()(st.code);
};
auto equal = [](const someType& st1, const someType& st2){
return st1.name == st2.name && st1.code == st2.code;
};
std::unordered_set<someType, decltype(hash), decltype(equal)> myset(8, hash, equal);
Code on Ideone
Is it possible to have a set(or unordered_set ) of functions in c++ like this?
set<function<void(int)>> funcSet;
I got something like this
error: invalid operands to binary expression
('const std::__1::function<void (int)>' and 'const std::__1::function<void (int)>')
{return __x < __y;}
How can I compare two functions?
A set has the requirement that its elements may be ordered using <. So to put functions in a set, you have to define an ordering for functions first. For example, this comparison considers all functions with the same type as equal:
#include <set>
#include <functional>
using namespace std;
typedef function<void(int)> fun;
bool operator<(const fun& f1, const fun& f2) {
return f2.target_type().name() < f2.target_type().name();
}
int main() {
set<fun> fset;
}
Likewise, for an unordered_set, you'd have to define a specialization of std::hash<fun>.
Edit: I've borrowed the target idea from another solution to make the comparison well-defined.
Edit2: The most meaningful comparison for arbitrary functions would probably look like this:
struct fun_comp {
template<typename Fun1, typename Fun2>
bool operator()(const Fun1& f1, const Fun2& f2) {
const char* c1 = f1._M_functor._M_pod_data;
const char* c2 = f2._M_functor._M_pod_data;
size_t sz = sizeof(f1._M_functor._M_pod_data);
return lexicographical_compare(c1, c1+sz, c2, c2+sz);
}
};
This is, obviously, completely unportable, depends on libstdc++-internals and will only compile with -fno-access-control, so you probably shouldn't actually do it like this.
Would a std::vector<std::function<void(int)>> work?
If you want to order your functions it seems like you'd be the only one who knew the order anyway.
Perhaps creating an enum to index the std::vector would also be helpful for ordering?
One of the interview questions asked me to "write the prototype for a C function that takes an array of exactly 16 integers" and I was wondering what it could be? Maybe a function declaration like this:
void foo(int a[], int len);
Or something else?
And what about if the language was C++ instead?
In C, this requires a pointer to an array of 16 integers:
void special_case(int (*array)[16]);
It would be called with:
int array[16];
special_case(&array);
In C++, you can use a reference to an array, too, as shown in Nawaz's answer. (The question asks for C in the title, and originally only mentioned C++ in the tags.)
Any version that uses some variant of:
void alternative(int array[16]);
ends up being equivalent to:
void alternative(int *array);
which will accept any size of array, in practice.
The question is asked - does special_case() really prevent a different size of array from being passed. The answer is 'Yes'.
void special_case(int (*array)[16]);
void anon(void)
{
int array16[16];
int array18[18];
special_case(&array16);
special_case(&array18);
}
The compiler (GCC 4.5.2 on MacOS X 10.6.6, as it happens) complains (warns):
$ gcc -c xx.c
xx.c: In function ‘anon’:
xx.c:9:5: warning: passing argument 1 of ‘special_case’ from incompatible pointer type
xx.c:1:6: note: expected ‘int (*)[16]’ but argument is of type ‘int (*)[18]’
$
Change to GCC 4.2.1 - as provided by Apple - and the warning is:
$ /usr/bin/gcc -c xx.c
xx.c: In function ‘anon’:
xx.c:9: warning: passing argument 1 of ‘special_case’ from incompatible pointer type
$
The warning in 4.5.2 is better, but the substance is the same.
There are several ways to declare array-parameters of fixed size:
void foo(int values[16]);
accepts any pointer-to-int, but the array-size serves as documentation
void foo(int (*values)[16]);
accepts a pointer to an array with exactly 16 elements
void foo(int values[static 16]);
accepts a pointer to the first element of an array with at least 16 elements
struct bar { int values[16]; };
void foo(struct bar bar);
accepts a structure boxing an array with exactly 16 elements, passing them by value.
& is necessary in C++:
void foo(int (&a)[16]); // & is necessary. (in C++)
Note : & is necessary, otherwise you can pass array of any size!
For C:
void foo(int (*a)[16]) //one way
{
}
typedef int (*IntArr16)[16]; //other way
void bar(IntArr16 a)
{
}
int main(void)
{
int a[16];
foo(&a); //call like this - otherwise you'll get warning!
bar(&a); //call like this - otherwise you'll get warning!
return 0;
}
Demo : http://www.ideone.com/fWva6
I think the simplest way to be typesafe would be to declare a struct that holds the array, and pass that:
struct Array16 {
int elt[16];
};
void Foo(struct Array16* matrix);
You already got some answers for C, and an answer for C++, but there's another way to do it in C++.
As Nawaz said, to pass an array of N size, you can do this in C++:
const size_t N = 16; // For your question.
void foo(int (&arr)[N]) {
// Do something with arr.
}
However, as of C++11, you can also use the std::array container, which can be passed with more natural syntax (assuming some familiarity with template syntax).
#include <array>
const size_t N = 16;
void bar(std::array<int, N> arr) {
// Do something with arr.
}
As a container, std::array allows mostly the same functionality as a normal C-style array, while also adding additional functionality.
std::array<int, 5> arr1 = { 1, 2, 3, 4, 5 };
int arr2[5] = { 1, 2, 3, 4, 5 };
// Operator[]:
for (int i = 0; i < 5; i++) {
assert(arr1[i] == arr2[i]);
}
// Fill:
arr1.fill(0);
for (int i = 0; i < 5; i++) {
arr2[i] = 0;
}
// Check size:
size_t arr1Size = arr1.size();
size_t arr2Size = sizeof(arr2) / sizeof(arr2[0]);
// Foreach (C++11 syntax):
for (int &i : arr1) {
// Use i.
}
for (int &i : arr2) {
// Use i.
}
However, to my knowledge (which is admittedly limited at the time), pointer arithmetic isn't safe with std::array unless you use the member function data() to obtain the actual array's address first. This is both to prevent future modifications to the std::array class from breaking your code, and because some STL implementations may store additional data in addition to the actual array.
Note that this would be most useful for new code, or if you convert your pre-existing code to use std::arrays instead of C-style arrays. As std::arrays are aggregate types, they lack custom constructors, and thus you can't directly switch from C-style array to std::array (short of using a cast, but that's ugly and can potentially cause problems in the future). To convert them, you would instead need to use something like this:
#include <array>
#include <algorithm>
const size_t N = 16;
std::array<int, N> cArrayConverter(int (&arr)[N]) {
std::array<int, N> ret;
std::copy(std::begin(arr), std::end(arr), std::begin(ret));
return ret;
}
Therefore, if your code uses C-style arrays and it would be infeasible to convert it to use std::arrays instead, you would be better off sticking with C-style arrays.
(Note: I specified sizes as N so you can more easily reuse the code wherever you need it.)
Edit: There's a few things I forgot to mention:
1) The majority of the C++ standard library functions designed for operating on containers are implementation-agnostic; instead of being designed for specific containers, they operate on ranges, using iterators. (This also means that they work for std::basic_string and instantiations thereof, such as std::string.) For example, std::copy has the following prototype:
template <class InputIterator, class OutputIterator>
OutputIterator copy(InputIterator first, InputIterator last,
OutputIterator result);
// first is the beginning of the first range.
// last is the end of the first range.
// result is the beginning of the second range.
While this may look imposing, you generally don't need to specify the template parameters, and can just let the compiler handle that for you.
std::array<int, 5> arr1 = { 1, 2, 3, 4, 5 };
std::array<int, 5> arr2 = { 6, 7, 8, 9, 0 };
std::string str1 = ".dlrow ,olleH";
std::string str2 = "Overwrite me!";
std::copy(arr1.begin(), arr1.end(), arr2.begin());
// arr2 now stores { 1, 2, 3, 4, 5 }.
std::copy(str1.begin(), str1.end(), str2.begin());
// str2 now stores ".dlrow ,olleH".
// Not really necessary for full string copying, due to std::string.operator=(), but possible nonetheless.
Due to relying on iterators, these functions are also compatible with C-style arrays (as iterators are a generalisation of pointers, all pointers are by definition iterators (but not all iterators are necessarily pointers)). This can be useful when working with legacy code, as it means you have full access to the range functions in the standard library.
int arr1[5] = { 4, 3, 2, 1, 0 };
std::array<int, 5> arr2;
std::copy(std::begin(arr1), std::end(arr1), std::begin(arr2));
You may have noticed from this example and the last that std::array.begin() and std::begin() can be used interchangeably with std::array. This is because std::begin() and std::end() are implemented such that for any container, they have the same return type, and return the same value, as calling the begin() and end() member functions of an instance of that container.
// Prototype:
template <class Container>
auto begin (Container& cont) -> decltype (cont.begin());
// Examples:
std::array<int, 5> arr;
std::vector<char> vec;
std::begin(arr) == arr.begin();
std::end(arr) == arr.end();
std::begin(vec) == vec.begin();
std::end(vec) == vec.end();
// And so on...
C-style arrays have no member functions, necessitating the use of std::begin() and std::end() for them. In this case, the two functions are overloaded to provide applicable pointers, depending on the type of the array.
// Prototype:
template <class T, size_t N>
T* begin (T(&arr)[N]);
// Examples:
int arr[5];
std::begin(arr) == &arr[0];
std::end(arr) == &arr[4];
As a general rule of thumb, if you're unsure about whether or not any particular code segment will have to use C-style arrays, it's safer to use std::begin() and std::end().
[Note that while I used std::copy() as an example, the use of ranges and iterators is very common in the standard library. Most, if not all, functions designed to operate on containers (or more specifically, any implementation of the Container concept, such as std::array, std::vector, and std::string) use ranges, making them compatible with any current and future containers, as well as with C-style arrays. There may be exceptions to this widespread compatibility that I'm not aware of, however.]
2) When passing a std::array by value, there can be considerable overhead, depending on the size of the array. As such, it's usually better to pass it by reference, or use iterators (like the standard library).
// Pass by reference.
const size_t N = 16;
void foo(std::array<int, N>& arr);
3) All of these examples assume that all arrays in your code will be the same size, as specified by the constant N. To make more your code more implementation-independent, you can either use ranges & iterators yourself, or if you want to keep your code focused on arrays, use templated functions. [Building on this answer to another question.]
template<size_t SZ> void foo(std::array<int, SZ>& arr);
...
std::array<int, 5> arr1;
std::array<int, 10> arr2;
foo(arr1); // Calls foo<5>(arr1).
foo(arr2); // Calls foo<10>(arr2).
If doing this, you can even go so far as to template the array's member type as well, provided your code can operate on types other than int.
template<typename T, size_t SZ>
void foo(std::array<T, SZ>& arr);
...
std::array<int, 5> arr1;
std::array<float, 7> arr2;
foo(arr1); // Calls foo<int, 5>(arr1).
foo(arr2); // Calls foo<float, 7>(arr2).
For an example of this in action, see here.
If anyone sees any mistakes I may have missed, feel free to point them out for me to fix, or fix them yourself. I think I caught them all, but I'm not 100% sure.
Based on Jonathan Leffler's answer
#include<stdio.h>
void special_case(int (*array)[4]);
void anon(void){
int array4[4];
int array8[8];
special_case(&array4);
special_case(&array8);
}
int main(void){
anon();
return 0;
}
void special_case(int (*array)[4]){
printf("hello\n");
}
gcc array_fixed_int.c &&./a.out will yield warning:
array_fixed_int.c:7:18: warning: passing argument 1 of ‘special_case’ from incompatible pointer type [-Wincompatible-pointer-types]
7 | special_case(&array8);
| ^~~~~~~
| |
| int (*)[8]
array_fixed_int.c:2:25: note: expected ‘int (*)[4]’ but argument is of type ‘int (*)[8]’
2 | void special_case(int (*array)[4]);
| ~~~~~~^~~~~~~~~
Skip warning:
gcc -Wno-incompatible-pointer-types array_fixed_int.c &&./a.out