std::array error: Has no member named 'assign' - c++

In the following code, the compiler complains as: struct std::array<double,5ul> has no member named 'assign'. Here, it seems possible. Why is it so? (Compiler: g++ 4.8.2)
#include <array>
int main()
{
std::array<double,5> arr;
arr.assign(4.); // error: has no member named 'assign'
return 0;
}

array::assign() is a Visual Studio extension. You are compiling with g++. Check here standard g++ array

As already mentioned, there simply is no assign member to std::array.
The interesting question now becomes why ? After all, the other containers have an assign member method !
I would note that unlike other containers, std::array has a fixed size. If you use std::vector<T>::assign (which would be a close equivalent), the vector is resized appropriately to match the size of the sequence being assigned; with an array, however, that would be impossible:
what would you do if the sequence being assigned is shorter than the array ?
what would you do if the sequence being assigned is longer than the array ?
this would be counter-intuitive, as the question does not arise for the other containers since their size is just adapted on the fly.
For a similar reason, std::array does not have: reserve, capacity, clear, insert, emplace, erase, push/pop (and variants) or resize. All of them suppose a container which size may vary.

That is very simple, as you can see here there is no assign member function for an std array. There is however a member function called fill you should be able to use.

The assign method it is not a member of std::array. The member fill does what the assign did in TR1.
assign was originally part of std::tr1::array (from the TR1) and was changed to be fill circa the C++0x (now C++11) draft n2798 (2008).
This is not really a Microsoft extension, I would imagine that they have probably maintained this method for compatibility with, and support for tr1 implementations in production (the method implementations are exactly the same).

Related

is it possible to declare a container of X as a member of X

I have this class :
#include <unordered_map>
class MyClass
{
// Trie node class
struct Node
{
std::unordered_map<char, Node> m_children;
// ...
}; // .....
};
int main()
{
MyClass m;
}
When compiling, I got this errors :
/usr/include/c++/7/bits/stl_pair.h:204:11: error: ‘std::pair<_T1,
_T2>::second’ has incomplete type
_T2 second; /// #c second is a copy of the second object
^~~~~~ AutocompleteModern.cpp:24:12: note: forward declaration of ‘struct Autocomplete::Node’
struct Node
^~~~
I know that if I use a pointer as a value in the hash map, this might work. But I wonder if it's possible to make the code above compile without changing the type the hash map's value. or is it impossible ?
You have a circular loop dependency: You say that m_children should contain Node objects, but at that point the class Node isn't defined (only declared).
You could use pointers (or references) to incomplete types though:
std::unordered_map<char, std::unique_ptr<Node>> m_children;
Note the use of std::unique_ptr, which is used to indicate that the map is the sole owner of the Node objects (and also has the added benefit of some automatic memory management).
It's possible for some containers, but std::unordered_map is not one of them. It might work with some implementations, but the standard doesn't require it to work for std::unordered_map (in fact it says its undefined to do it). So even if it compiled today, with a particular compiler, it might not work tomorrow.
The containers that can be declared with incomplete types are std::forward_list, std::list, and std::vector. So those containers can be used as a member of a class, before the class definition is complete)
But I wonder if it's possible to make the code above compile without changing the type the hash map's value. or is it impossible ?
It is impossible, because the compiler cannot compute a meaningful (and finite) sizeof for that MyClass.
Put yourself in the compiler shoes: it has to compute a layout, and a byte size (as given by sizeof) for MyClass quite early when compiling your code. And it obviously could not.
In C++, for such circularity, you have to use pointers (but you could "hide" them as smart pointers, etc.).
(So this answer is a rationale or an intuition for Some programmer dude's answer)
There is also another (purely "legal") reason: the C++11 standard n3337 forbids that. I leave up to you to check (and find precisely what clause there forbids that).
PS. As commented by songyanyo, you might find some particular C++ standard library implementation where your code is accepted (I guess that on such implementations, more hidden pointers are used). This is not the case on my Linux Debian Sid box (both with GCC 8 and Clang 7). In practice you want to write code that is compilable on your box. I have no idea which particular C++ standard library is the most conforming to the standard, but the intuition above stays.

Workaround for zero-sized arrays in standard C++14?

I am developing a binding toolkit for Google's V8 ECMAScript engine.
Consider this templated function:
template<class... Types> void call_v8_function(v8::Local<v8::Function> function,
Types... args) {
...significant amount of context set-up here...
v8::Local<v8::Value> call_args[] = { V8Utils::to_js_value(isolate, args)... };
function->Call(this->context, sizeof...(args), call_args);
}
It takes a variable number of arguments and maps them to an array of v8::Value objects using a helper function. (the arguments can have arbitrary types, as long as they're recognized by to_js_value) This works wonderfully when I compile using GCC or Clang.
In Visual Studio, however, it completely breaks down. When this templated function is called without any additional arguments, an array of size 0 is being declared. While accepted by GCC and Clang, the standard doesn't permit this and Visual Studio rightfully spits out error C2466: cannot allocate an array of constant size 0.
Because I find this approach to be very convenient, I'm looking for a way to make it work, other than duplicating the function for the no-arguments case, as that would lead to a significant code duplication.
Instead of c-style array, you could use a std::array which already has a specialization for zero-sized arrays. Furthermore, for your function call the data() member is also well-behaved for empty arrays.

Differences between std::array and boost::array

It is fully safe to change boost::array to std::array? Can it cause any discrepancies?
Is boost::array better over std::array (performance?)?
std::array<T,N> and boost::array<T,N> are standard layout aggregates containing nothing but an array of T[N].
Their interaction with namespace boost and namespace std may be different (Specifically, ADL will find std functions for std::array, and boost functions for boost::array).
So, if there is a function foo in boost, calling foo(some_array) might work if some_array was from boost, and not if it was from std.
The only container algorithms currently in std are std::begin and std::end (and similar the new ones size empty etc if you include near-future ones). Ranges v3 (or whatever gets published) might add some more.
There are more container algorithms in boost than in std. Some of them might fail to build.
In the worst case, someone could write a function with the same name as a container algorithm in boost, with an argument that can implicitly convert from std::array, and the unqualified call to that function could result in a conversion after you change the variable type, while before it called the boost container algorithm.
Similarly, someone could write code that explicitly checks if a template argument is a boost::array and behave differently if it is.
Both of those are a bit of a stretch.
Finally, std::array has modern noexcept decoration, and boost has a public c_array member you can get at (the name std::array member variables is, I believe, not specified). (via #Potatoswatter). I'd personally expect std::array to have better support going forward, as boost::array mainly existed because std lacked the functionality.
Other than those corner cases, std::array should be a drop-in replacement.

'base' no member of iterator in C++ anymore

I am trying to compile some code that was originally build in MS Visual Studio C++ 6.0 with Visual Studio 2013.
In the old code the following construct was often used for various data types (here for example for a string):
std::string someString;
someString = ....;
callSomeFunction(someString.begin().base());
So in order to enable the function to edit (in this example the string) the original buffer, the method begin() gets an iterator for it and the method base() returned a pointer to the first element of the buffer.
In the code this is not only used for strings, but for many many other datatypes as well.
Thus I was wondering, if there was a change to the standard library so the base() method is no longer supported?
Is there any replacement for it? Or do I have to change the code here? Since this was used very frequently, I would prefer to find a simpler solution to this.
Currently I get an error like:
Error 3 error C2039: 'base' : is not a member of 'std::_Vector_iterator>>'
base was not standardized for container iterators. It exists for iterator adaptors such as std::reverse_iterator and std::move_iterator. Microsoft had to remove it from their implementation in order to comply with the ISO C++ standard.
To obtain a pointer from a container iterator, simply use &* iter. To get a pointer to the first element of the contiguous array backing a container, use cont.data().
You can just pass in:
callSomeFunction(&someString[0]);
That will be a char*. However, it would be safer and preferred if you could just change the signature of the function to take a std::string& - especially if there's any potential in that function just writing past the end of someString. I realize that's not always possible though.

Array or vector declaration for aligned datatype Eigen::Matrix

I have an class ClusterNode which contains an Eigen::Matrix4d as a class variable. I also have a function numNodes() which tells me the total number of ClusterNodes, so that I can collect them in some sort of array, list, or vector.
However, Eigen::Matrix4d is aligned which means I cannot store objects of this type in a std::vector<ClusterNode> as per the answer to this question error C2719: '_Val': formal parameter with __declspec(align('16')) won't be aligned?
As an alternative, I have tried using an array.
However, I cannot do
const int n = numNodes();
ClusterNode array [n];
Because the return value of a function is not considered a constant.
What other options do I have?
You can use Eigen's aligned_allocator. See this page for the details, but basically you can do:
std::vector<ClusterNode, Eigen::aligned_allocator<ClusterNode> >
Also don't forget to overload operator new for your class. Again, all the details are in the Eigen's documentation.
You can try to use memalign or posix_memalign to allocate and align a variable memory space
http://man.he.net/man3/memalign
I ended up using Alex Faber's solution
ClusterNode* array = new ClusterNode[n];
But I wanted to add the note that, in this case, the class also needs to return alligned pointers. It will only cause problems part of the time, in a very annoying and untracable way, but after much bug hunting, I finally got a useful error message that pointed me to Eigen's documentation.
A summary of the documentation: Eigen needs 16-byte aligned memory. The following cases will lead to grief.
std containers containing Eigen types
classes or structures containing Eigen types
passing Eigen types to functions by value
gcc on Windows has wrong alignment (4-byte)
If I use the dynamic array solution proposed by Alex (ClusterNode as a variable at all for that matter), I also need to use a macro provided by Eigen to ensure that the objects are aligned. For example,
class ClusterNode
{
Eigen::Matrix4d M;
public:
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
}
If the macro is not included, the array declaration will sometimes silently fail.