Auto type vectors - c++11

I just read about vectors in C++. They seem to be like lists in Python, but they can only take values of the datatype specified in the declaration. For example:
vector<int> intlist;
Takes only int type data. Whereas a list in Python take any type of data. I tried to implement the same in C++ by writing:
vector<auto> list;
But it resulted in an erroneous compilation. I am not sure why this happens as it works fine with other datatypes.

You're doing it the wrong way.
C++ is strong typed. auto is a keyword used when the type of variable can be determined at compile time, that's not what you want.
If you need to have a vector of object of different types, you must use some library like boost::any.
EDIT:
C++ is statically typed and Python dinamically typed, this is the difference. Thanks to #Angew for correcting my mistake.

auto is not a variant type, it is simply a shortcut you can use in your code when the type can be deduced by the compiler.
Underneath a Python list is some implementation of a variant and I would suggest using boost::python to manage C++ - Python interaction.

Also, if this is something you really want to achieve in c++ I recommend switching to c++17 and using std::variant. This is an example of using std::variant which at face-value may seem somewhat similar to a python array.
#include <variant>
#include <iostream>
#include <string>
using my_variant = std::variant<std::string, float, int, bool>;
int main(){
std::vector<my_variant> list = {"hello", 5.0, 10.0, "bye", false};
for(int i = 0; i < list.size(); i++){
std::visit([](auto arg){std::cout<<arg<<std::endl;}, list.at(i));
}
return 0;
}

Related

Initialisation of a std::string seems to generate the same code no matter which initialisation I use (uniform, assignment, etc)

I was experimenting with C++ Insights and I got a result that was surprising to me and which I don't really understand. I was hoping some one can provide some illumination for.
Given this code snippet:
#include <string>
int main()
{
std::string a {"123"};
std::string b = {"123"};
std::string c = "123";
std::string d("123");
}
I was at least expecting a to be initialised differently to c. With c I was expecting some sort of temporary string to be copied and for a I was expecting just the constructor to be called directly.
Here is the link to c++ insights: here (You have to press the "play" button).
Every one of the different ways to initialise a string is the same. This really surprised me. I started with c++17 and then switched to c++11, which produced something more like what I was expecting.
Does this mean that all init types in c++17 are now the same? - is there a name for this, because I thought uniform init was only with the curly braces {} - is everything now uniform init?

using std::max causes a link error?

Consider a library that defines in a header file
struct Proj {
struct Depth {
static constexpr unsigned Width = 10u;
static constexpr unsigned Height = 10u;
};
struct Video {
static constexpr unsigned Width = 10u;
static constexpr unsigned Height = 10u;
};
};
The library gets compiled, and I'm now developing an application that links against this library. I thought for a long time it was some kind of visibility problem, but even after adding B_EXPORT (standard visibility stuff from CMake) everywhere with no change, I finally found the problem.
template <class Projection>
struct SomeApplication {
SomeApplication() {
unsigned height = std::max(// or std::max<unsigned>
Projection::Depth::Height,
Projection::Video::Height
);
}
};
I can't even reproduce the problem with a small dummy library / sample application. But using std::max in the application causes the link error, whereas if I just do it myself
unsigned height = Projection::Depth::Height;
if (height < Projection::Video::Height)
height = Projection::Video::Height;
Everything works out. AKA there don't appear to be any specific issues with the visibility in terms of just using Projection::XXX.
Any thoughts on what could possibly cause this? This is on OSX, so this doesn't even apply.
The problem is that Width and Height are declared, not defined in your structs. Effectively, this means there is no storage allocated for them.
Now recall the signature for std::max:
template<typename T>
const T& max(const T&, const T&);
Note the references: this means the addresses of the arguments are to be taken. But, since Width and Height are only declared, they don't have any storage! Hence the linker error.
Now let's consider the rest of your question.
Your hand-written max works because you never take any pointers or references to the variables.
You might be unable to reproduce this on a toy example because, depending on the optimization level in particular, a sufficiently smart compiler might evaluate max at compile time and save the trouble of taking the addresses at runtime. For instance, compare the disasm for no optimization vs -O2 for gcc 7.2: the evaluation is indeed done at compile-time!
As for the fix, it depends. You have several options, to name a few:
Use constexpr getter functions instead of variables. In this case the values they return will behave more like temporary objects, allowing the addresses to be taken (and the compiler will surely optimize that away). This is the approach I'd suggest in general.
Use namespaces instead of structs. In this case the variables will also be defined in addition to being declared. The caveat is that you might get duplicate symbol errors if they are used in more than one translation unit. The fix for that is only in form of C++17 inline variables.
...speaking of which, C++17 also changes the rules for constexpr static member variables (they become inline by default), so you won't get this error if you just switch to this standard.

static_assert fails when test condition includes constants defined with const?

I'm reading Bjarne Stroustrup's book, "The C++ Programming Language" and I found an example explaining static_assert. What I understood is that static_assert only works with things that can be expressed by constant expressions. In other words, it must not include an expression that's meant to be evaluated at runtime.
The following example was used in the book (I did some changes in the code. But I don't think that should change anything that'd be produced by the original example code given in the book.)
#include <iostream>
using namespace std;
void f (double speed)
{
constexpr double C = 299792.468;
const double local_max = 160.0/(60*60);
static_assert(local_max<C,"can't go that fast");
}
int main()
{
f(3.25);
cout << "Reached here!";
return 0;
}
The above gives a compile error. Here's it compiled using ideone: http://ideone.com/C97oF5
The exact code from the book example:
constexpr double C = 299792.458;
void f(double speed)
{
const double local_max = 160.0/(60∗60);
static_assert(speed<C,"can't go that fast"); // yes this is error
static_assert(local_max<C,"can't go that fast");
}
The compiler does not know the value of speed at compile time. It makes sense that it cannot evaluate speed < C at compile time. Hence, a compile time error is expected when processing the line
static_assert(speed<C,"can't go that fast");
The language does not guarantee that floating point expressions be evaluated at compile time. Some compilers might support it but that's not to be relied upon.
Even though the values of the floating point variables are "constants" to a human reader, they are not necessarily evaluated at compile time. The error message from the compiler from the link you provided makes it clear.
static_assert expression is not an integral constant expression
You'll have to find a way to do the comparison using integral expressions. However, that seems to be a moot point. I suspect, what you really want to do is make sure that speed is within a certain limit. That makes sense only as a run time check.

Copy from vector<T> to vector<U>, using C++11 features

I have a std::vector<char*> that I want to copy into a std::vector<MemRef>, in a performance-critical section. I've looked at solutions using std::copy(), boost::make_transform_iterator, std::vector<int> newVec; newVec.reserve(oldVec.size()); .. push_back() and I have no idea what's best.
MemRef is a small object containing a char* and a size_t length.
I'm using GCC 4.4.7 with --std=g++0x so I get some c++ features, including emplace_back() which is nice for avoiding constructors and copying.
I think I'm better off not constructing the vector afresh each time, but rather using the vector clear() method to empty it, which as I understand allows it to refill to capacity without reallocation.
I'd appreciate help getting my head around this!
I think std::copy would have pretty good performance, especially with the one note I see on cppreference.com
In practice, implementations of std::copy avoid multiple assignments
and use bulk copy functions such as std::memmove if the value type is
TriviallyCopyable
If the types require conversion then I would do this:
class MemRef
{
public:
MemRef(char * astr) : ptr_( astr), size_( strlen( astr)) { }
...
} ;
vecMem.insert(vecMem.end(), cstrVec.begin(), cstrVec.end()) ;
This allows vecMem to figure out how much space it needs to reserve in one go.

Code compiles in VS2008 but not in VS2010 for std::set with boost::trim

The following code
#include "stdafx.h"
#include <string>
#include <set>
#include <boost/algorithm/string/trim.hpp>
int _tmain(int argc, _TCHAR* argv[])
{
std::set<std::string> test;
test.insert("test1 ");
test.insert("test2 ");
for(std::set<std::string>::iterator iter = test.begin(); iter != test.end(); ++iter)
{
boost::algorithm::trim(*iter);
}
return 0;
}
compiles in VS2008 but fails in VS2010 with the error
error C2663: 'std::basic_string<_Elem,_Traits,_Ax>::erase' : 3 overloads have no legal conversion for 'this' pointer \boost\include\boost\algorithm\string\trim.hpp
which indicates there is a problem with const matching in the functions. If I change set to vector everything is fine. I can also do a
boost::algorithm::trim(const_cast<std::string&>(*iter));
but I hate putting that in my code, and it seems like I shouldn't have to as I'm not using a const iterator on the set. Does anyone have any ideas if this is the intended behavior and why?
The elements of a std::set are intended to be immutable. If you could update them in place, it would either require the set to be re-ordered whenever you updated an element (which would be very hard, possibly impossible, to implement), or updating an element would break the set's guarantee of ordering.
Allowing the elements of a set to be mutable was an oversight in the original C++98 standard. It was corrected in C++11; the new standard requires set iterators to dereference to a const element. VS10 implements the new rule; VS08 followed the old standard, where updating a set element in place invokes undefined behaviour.
(See the final draft C++11 standard, section 23.2.4 para 6.)
Yes, it's intended behavior. Even when you don't use a const_iterator, you normally need to treat the contents of a set as const. Even though the modification you're making (probably) shouldn't cause a problem, modifying them in general could require that the order of the elements be changed to maintain set's invariant that the items are always in order.
To ensure that they stay in order, you aren't allowed to modify them at all.
VS 2008 allowed this, but probably shouldn't have (as in: the standard sort of allowed it, but it definitely wasn't a good idea). VS 2010 fixes the problem (and conforms with the new draft standard) by not allowing in-place modification.
The cure is to remove the item from the set, modify as needed, and then re-insert it into the set (or, as you've done, cast away the const-ness, and pray that nothing you do screws up the ordering).

Resources