I'm trying to use emplace() to construct in-place a map<K,V> entry (using Boost). The key object constructor arg gets forwarded through the template magic correctly, but the V object constructor arg becomes const, so it doesn't work.
#include <boost/container/map.hpp>
class A {
public:
/**/ A( int n ) { }
friend bool operator<( const A &a1, const A &a2 ) { return false; }
} ;
class B {
public:
/**/ B( const char *str ) { }
} ;
class C {
public:
/**/ C( B &b ) { }
} ;
int
main( int, char ** )
{
boost::container::map<A,B> m1;
boost::container::map<A,C> m2;
B b( "Foo" );
C c( b ); // <--- this works OK.
m1.emplace( 1, "Hello" );
m2.emplace( 2, b ); // <----- this fails!
}
The Error is:
Error: /usr/local/include/boost/container/detail/pair.hpp:128:38: error: no matching function for call to C::C(const B&), second(::boost::forward<V>(v))
Something about the emplace argument-forwarding turns b into const b in the last line. I know there must be a boost::bla_bla_bla that I can apply to make it work, but I haven't been able to find it.
Can anybody help?
Note that if you compile this using -std=c++11 (or later), this will work. Why this is the case took a bit of digging - I'm using a slightly older version of boost (1.56), but I doubt this has changed much between the two releases.
Using emplace generally requires perfect forwarding. This means all of the arguments are forwarded as via std::forward<Args>(args).... Underneath, this relies on reference collapsing and move semantics - this is all C++11 territory, and has no analog in C++03.
If we dig into the boost code for pair (where it's actually generating the error), then this is the constructor it's attempting to call:
template<class U, class V>
pair(BOOST_FWD_REF(U) u, BOOST_FWD_REF(V) v)
: first(::boost::forward<U>(u))
, second(::boost::forward<V>(v))
{}
Unfortunately, BOOST_FWD_REF (which is in move/core.hpp) is one of the following:
#define BOOST_FWD_REF(TYPE)\
const TYPE & \
//
#define BOOST_FWD_REF(TYPE)\
const TYPE & \
//
When your compiler does not recognise rvalue references, this will then become const TYPE&.
There's a bit of discussion on this on the boost archives list.
The easiest solution is to simply compile with std=c++11.
Related
If one creates a const reference to a temporary, its life is extended as if the reference where in the stack.
It is a good feature of the language, although it is presented sometimes like an exception to other rules.
https://herbsutter.com/2008/01/01/gotw-88-a-candidate-for-the-most-important-const/
However this doesn't work when the const reference is part the member of a class.
Is this an inconsistency of the language?
Example code:
int f(int a){return a + 5;}
int main(){
int const& b = f(2);
assert(b == 7); // ok, not a dangling reference
struct single{
int const& m_;
single(int const& m) : m_(m){}
};
single s{f(3)};
assert(s.m_ == 8); // fails, dangling reference
struct pair{
int const& m1_;
int const& m2_;
pair(int const& m1, int const& m2) : m1_(m1), m2_(m2){}
};
pair p{f(3), f(4)};
assert( p.m1_ == 8 ); // fails, dangling reference
}
Is there a workaround for this to work or at least behave more consistently?
I found this to be a limiting factor in a few contexts now. For example, List using with references, changes behavior when used as a member and https://stackoverflow.com/a/51878764/225186
EDIT1: In other answers to similar questions is mentioned that the problem is that the constructor takes a const& where the rule doesn't apply.
However a perfect forward still fails.
In this case, either the inconsistency in the language is more evident or perfect forward is not as perfect.
struct single{
int const& m_;
template<class T>
single(T&& m) : m_(std::forward<T>(m)){}
};
EDIT2: Declaring single const& s{f(3)}; still doesn't help.
However "moving" the constness to the structure helps.
struct single{
int m_; // no const!
template<class T>
single(T&& m) : m_(std::forward<T>(m)){}
};
...
single const& s{f(3)}; // const ref with extended lifetime
So, perhaps it is good practice to transfer the constness to the whole struct.
I still think that reference members behave weirdly in the language. https://www.youtube.com/watch?v=uYDt1gCDxhM
EDIT3: As #Oliv mentions, the situation improves if one uses agregate initialization. However this is quite limiting.
struct single{
int const& m_;
};
...
single s{f(3)};
assert(s.m_ == 5);
I've been trying to streamline some of my code, condensing and making calls easier where I can. One of the things I've been trying to do is fuse two common overloads I have all over the place into one. They are as follows:
void MyClass::addSomething(Something & a)
{
vectorOfSomething.push_back(&a)
}
void MyClass::addSomething(std::vector<Something*> a)
{
for (unsigned int i = 0; i < a.size(); i++)
vectorOfSomething.push_back(a[i]);
}
The class Something is abstract. vectorOfSomething is a vector of pointers to Somethings.
Essentially, instead of having to do this:
std::Vector mySomethings = {&something1, &something2};
addSomething(mySomethings);
I want to do this:
addSomething({something1, something2});
So it is more similar to the first overload (no need for the user to create a vector of pointers first). Looking around the two ways I saw were either through: std::initializer_list or variadic templates, both of which I am not afraid to admit is completely foreign to me.
I've given it a shot with initializer lists but have run into a ton of errors trying various things. I've managed to get the function to actually accept the list, but I can't quite figure out how to get it to populate the vector correctly. The main issue seems to be that the init list has values that are 'const' within.
If anyone has any idea on how to make this work I would be grateful!
Something like this :
#include <iostream>
#include <initializer_list>
#include <vector>
#include <list>
struct MyClass {
template <typename It >
void Add( It b, It e ) {
data_.insert( end(data_), b, e );
}
void Add( std::initializer_list<int> const & elems ) {
Add( begin(elems), end(elems) );
}
template <typename T>
void Add( T const & cont ) {
Add( begin(cont), end(cont) );
}
std::vector<int> data_;
friend std::ostream & operator<<( std::ostream & os, MyClass const & mc ) {
for( auto & e : mc.data_ )
os << e << " ";
return os;
}
};
int main() {
MyClass foo;
foo.Add( { 1, 3 });
std::vector<int> v { 1,2};
foo.Add( v );
std::list<int> l { 4,5};
foo.Add( l );
std::cout << foo;
}
A compiler cannot infer a template argument to initializer_list, the specialization has to be explicit.
Let's say I am creating an Abstract Base Class for the purpose of defining a public interface. I want operator+ to be a part of this public interface. It would seem that this is not possible in C++ or that I am missing something.
For example, suppose the code below is a .h file declaring the public interface for an abstract base class named IAbstract. This code does not compile because I cannot declare a function that returns an instance of an abstract base class. This compile error makes sense, but what I don't understand is this: Is there any way to guarantee operator+ will exist in the public interface of IAbstract?
#include <iostream>
// An abstract base class
class IAbstract
{
public:
IAbstract(int value);
virtual ~IAbstract() {}
virtual int SomeOtherFunction() =0;
//This is ok
virtual IAbstract& operator++() =0;
//This will not compile
virtual const IAbstract operator+(const IAbstract& rhs) =0;
//Xcode5 says "Semantic Issue: Return type 'IAbstract' is an abstract class"
};
In addition to the return by value problem, the really problem with your dessign is the way that the C++ language works.
Object oriented languages like Java defines and transmit functionality through class hierarchies, interfaces, and polymorphism. Your code is the typical example of that.
C++ does not work in that way. C++ defines functionality through abstract concepts, and classes only need to fulfill this concepts to be usable in a certain way. How/if a class follows or implements a certain concept depends on its behavior, the implementation of certain functions (Like overloaded operators), etc.
So the C++ way to do what you are trying to achieve is to overload the required operators in a generic way, to ensure all classes that would implement the concept works with it.
In other words, if you are trying to make an addable concept, that is, represent things that could be added with others, a class only have to overload operator+. If a class overloads operator+ its addable. Just simple.
Here is another example: The classic implementation of std::copy():
template<typename IT , typename DEST_IT>
void copy( IT begin , IT end , DEST_IT dest_begin )
{
while( begin != end )
*dest_begin++ = *begin++;
}
In that implementation, whats the type of begin and end? Simple answer: We don't know. Could be anything. But could be anything that must fulfill the requirements of our function, that is: Is dereferenciable, incrementable, and comparable. In other words: Its an iterable type. A type that works (And seems like) an iterator.
So std::copy() works with any ranges represented by iterable things. Could be arrays:
int main()
{
int a[] = { 1,2,3 };
int b[3];
int* begin_a = &a[0];
int* end_a = &a[2];
int* begin_b = &b[0];
//Pointers are an iterable thing, right?:
std::copy( begin_a , end_a , begin_b );
//Or just the common generic way (Which does exactly the same):
std::copy( std::begin( a ) , std::end( a ) , std::begin( a ) );
}
Vectors, lists, etc:
int main()
{
std::vector<int> a = { 1,2,3 };
std::vector<int> b;
//Wooh, the code is exactly the same! Thats why templates are cool.
std::copy( std::begin( a ) , std::end( a ) , std::begin( a ) );
}
More freaking things, like iterators to walk through an stream:
int main()
{
std::vector<int> a = { 1,2,3 };
//Copy a vector to the standard output? Yes we can!
std::copy( std::begin( a ) , std::end( a ) , std::ostream_iterator<int>( std::cout , "\n" ) );
}
1
2
3
And your own classes:
struct numeric_iterator
{
int value;
numeric_iterator( int initial_value = 0 ) : value( initial_value ) {}
//numeric_iterator is an iterable thing because...
//... its dereferenciable
int operator*() const
{
return value;
}
//... its incrementable
numeric_iterator& operator++()
{
++value;
return *this;
}
numeric_iterator operator++(int)
{
numeric_iterator copy( *this );
++(*this);
return copy;
}
//... and its comparable
friend bool operator==( const numeric_iterator& lhs , const numeric_iterator& lhs )
{
return lhs.value == rhs.value;
}
friend bool operator!=( const numeric_iterator& lhs , const numeric_iterator& lhs )
{
return !( lhs == rhs );
}
};
int main()
{
//Tah dah!
std::copy( numeric_iterator( -4 ) ,
numeric_iterator( 5 ) ,
std::ostream_iterator<int>( std::cout , " " )
);
}
-4 -3 -2 -1 0 1 2 3 4
The offending line is:
virtual const IAbstract operator+(const IAbstract& rhs) =0;
That method returns by value, thus copying and creating an object of type IAbstract, which is not allowed. You should change to:
virtual const IAbstract& operator+(const IAbstract& rhs) =0;
That seems to be your intent but an easy oversight.
Somewhere you have: IAbstract variable and you can never actually have an IAbstract, only pointers to it (or references).
It is annoyed because somewhere you try and deal with a IAbstract.
It wants IAbstract* or IAbstract& or IAbstract&& which are all fine (in some form (const and volatile, so forth)).
There you go, you are returning IAbstract from operator++, which makes no sense, because you can never have a IAbstract, just look at something as one.
No, it is not possible guarantee operator+ will exist in the public interface of IAbstract-derived classes because you cannot properly declare operator+ as a pure virtual function.
The trick is to encapsulate the abstract base class, inside a regular type. The solution requires that there is a clone method
class AbstractNumericType
{
public:
virtual AbstractNumericType& operator+=(AbstractNumericType const& other) = 0;
virtual std::unique_ptr<AbstractNumeric> clone() = 0;
virtual ~AbstractNumericType() = default;
};
class NumericType
{
public:
template<class Something>
NumericType(Something value):m_obj{createNumber(value)}
{}
NumericType(NumericType const& other): m_obj{other.m_obj->clone()}
{}
NumericType operator+(NumericType const& other) const
{
auto ret = *this;
(*ret.m_obj) += (*other.m_obj);
return ret;
}
private:
std::unique_ptr<AbstractNumericType> m_obj;
};
Demo: https://gcc.godbolt.org/z/e4v1Tr
The real problem here is how you can implement operator+= when you do not have the concrete type available. You could add multiple overloads (like visitor pattern), or you could use a type switch based on rtti. None of these solutions is really good.
I've recently run into a quite a few situations where the Named Parameter Idiom would be useful, but I'd like it to be guaranteed in compile-time. The standard method of returning references in a chain almost always appears to invoke a run-time constructor (compiling with Clang 3.3 -O3).
I haven't been able to find anything with reference to this so I tried to get this to work with constexpr and got something functional:
class Foo
{
private:
int _a;
int _b;
public:
constexpr Foo()
: _a(0), _b(0)
{}
constexpr Foo(int a, int b)
: _a(a), _b(b)
{}
constexpr Foo(const Foo & other)
: _a(other._a), _b(other._b)
{}
constexpr Foo SetA(const int a) { return Foo(a, _b); }
constexpr Foo SetB(const int b) { return Foo(_a, b); }
};
...
Foo someInstance = Foo().SetB(5).SetA(2); //works
While this is okay for a small number of parameters, for larger numbers it quickly blows up into a mess:
//Unlike Foo, Bar takes 4 parameters...
constexpr Bar SetA(const int a) { return Bar(a, _b, _c, _d); }
constexpr Bar SetB(const int b) { return Bar(_a, b, _c, _d); }
constexpr Bar SetC(const int c) { return Bar(_a, _b, c, _d); }
constexpr Bar SetD(const int d) { return Bar(_a, _b, _c, d); }
Is there a better way? I'm looking at doing this with classes that have many (30+) parameters and this seems like it would be prone to error if extended in the future.
EDIT: Removed C++1y tag -- while C++1y does appear to fix the problem (thanks TemplateRex!) this is for production code, and we are stuck with C++11. If that means its impossible, then I guess that's just the way it is.
EDIT2: To show why I'm looking for this, here's a use case. Currently with our platform, developers need to explicitly set bit vectors for hardware configurations, and while this is okay it's very error prone. Some are using designated initializers from the C99 extension, which is okay but non-standard:
HardwareConfiguration hardwareConfig = {
.portA = HardwareConfiguration::Default,
.portB = 0x55,
...
};
Most, however, aren't even using this, and are just inputting a blob of numbers. So as a working improvement, I'd like to move towards something like this (since it also forces better code):
HardwareConfiguration hardwareConfig = HardwareConfiguration()
.SetPortA( Port().SetPolarity(Polarity::ActiveHigh) )
.SetPortB( Port().SetPolarity(Polarity::ActiveLow) );
Which might be far more verbose, but much clearer when reading later.
Using Template Metaprogramming
Here is something I came up with to solve your problem (at least partially). By using template metaprogramming, you can leverage the compiler to do most of the job for you. These techniques look weird for those who have never seen such code before, but thankfully most of the complexity can be hidden away in a header and the users only interact with the library in a neat and terse manner.
A Sample Class Definition and its Use
Here is an example of what defining a class would entail on your part:
template <
//Declare your fields here, with types and default values
typename PortNumber = field<int, 100>,
typename PortLetter = field<char, 'A'>
>
struct MyStruct : public const_obj<MyStruct, PortNumber, PortLetter> //Derive from const_obj like this, passing the name of your class + all field names as parameters
{
//Your setters have to be declared like this, by calling the Set<> template provided by the base class
//The compiler needs to be told that Set is part of MyStruct, probably because const_obj has not been instantiated at this point
//in the parsing so it doesn't know what members it has. The result is that you have to use the weird 'typename MyStruct::template Set<>' syntax
//You need to provide the 0-based index of the field that holds the corresponding value
template<int portNumber>
using SetPortNumber = typename MyStruct::template Set<0, portNumber>;
template<int portLetter>
using SetPortLetter = typename MyStruct::template Set<1, portLetter>;
template<int portNumber, char portLetter>
using SetPort = typename MyStruct::template Set<0, portNumber>
::MyStruct::template Set<1, portLetter>;
//You getters, if you want them, can be declared like this
constexpr int GetPortNumber() const
{
return MyStruct::template Get<0>();
}
constexpr char GetPortLetter() const
{
return MyStruct::template Get<1>();
}
};
Using the Class
int main()
{
//Compile-time generation of the type
constexpr auto myObject =
MyStruct<>
::SetPortNumber<150>
::SetPortLetter<'Z'>();
cout << myObject.GetPortNumber() << endl;
cout << myObject.GetPortLetter() << endl;
}
Most of the job is done by the const_obj template. It provides a mechanism to modify your object at compile time. Much like a Tuple, the fields are accessed with 0-based indices but this does not stop you from wrapping the setters with friendly names, as is done with SetPortNumber and SetPortLetter above. (They just forward to Set<0> and Set<1>)
About Storage
In the current implementation, after all the setters have been called and the object declared, the fields end up being stored in a compact array of const unsigned char's named data in the base class. If you use fields that are not unsigned chars (as in done above with PortNumber for example) the field is divided in big endien unsigned char's (could be changed to little endien as needed). If you don't need an actual storage that has an actual memory address, you could omit it altogether by modifying the packed_storage (see full implementation link below) and the values would still be accessible at compile time.
Limitations
This implementation only allows integral types to be used as fields (all flavors of shorts, ints, longs, bool, char). You can still provide setters that act on more than one field though. Example:
template<int portNumber, char portLetter>
using SetPort = typename MyStruct::template Set<0, portNumber>::
MyStruct::template Set<1, portLetter>;
Full Code
The full code for the implementation of this little library can be found here:
Full Implementation
Additional Notes
This code has been tested and works with the C++11 implementation of both g++ and clang.
It has not been tested for hours and hours so of course there may be bugs but it should provide you with a good base to start with. I hope this helps!
In C++14, constraints on constexpr function will be relaxed, and the usual chaining of reference-returning setters will work at compile-time:
#include <iostream>
#include <iterator>
#include <array>
#include <utility>
class Foo
{
private:
int a_ = 0;
int b_ = 0;
int c_ = 0;
int d_ = 0;
public:
constexpr Foo() = default;
constexpr Foo(int a, int b, int c, int d)
:
a_{a}, b_{b}, c_{c}, d_{d}
{}
constexpr Foo& SetA(int i) { a_ = i; return *this; }
constexpr Foo& SetB(int i) { b_ = i; return *this; }
constexpr Foo& SetC(int i) { c_ = i; return *this; }
constexpr Foo& SetD(int i) { d_ = i; return *this; }
friend std::ostream& operator<<(std::ostream& os, const Foo& f)
{
return os << f.a_ << " " << f.b_ << " " << f.c_ << " " << f.d_ << " ";
}
};
int main()
{
constexpr Foo f = Foo{}.SetB(5).SetA(2);
std::cout << f;
}
Live Example using Clang 3.4 SVN trunk with std=c++1y.
I'm not sure if classes with 30 parameters are a good idea (Single Responsiblity Principle and all that) but at least the above code scales linearly in the number of setters, with only 1 argument per setter. Note also that there are only 2 constructors: the default one (which takes its arguments from the in-class initializers) and the full one which takes 30 ints in your ultimate case).
Consider:
std::tuple<int , const A&> func (const A& a)
{
return std::make_tuple( 0 , std::ref(a) );
}
Is the std::ref required for writing correct and portable code? (It compiles fine without it)
Background:
If I remove std::ref my code builds fine without any warnings (g++-4.6 -Wall), but doesn't run correctly.
In case of interest the definition of A:
struct A {
std::array<int,2> vec;
typedef int type_t;
template<typename... OPs,typename... VALs>
A& operator=(const std::pair< std::tuple<VALs...> , std::tuple<OPs...> >& e) {
for( int i = 0 ; i < vec.size() ; ++i ) {
vec[i] = eval( extract(i,e.first) , e.second );
}
}
};
One of the example where std::ref is necessary:
void update(int &data) //expects a reference to int
{
data = 15;
}
int main()
{
int data = 10;
// This doesn't compile as the data value is copied when its reference is expected.
//std::thread t1(update, data);
std::thread t1(update, std::ref(data)); // works
t1.join();
return 0;
}
The std::thread constructor copies the supplied values, without converting to the expected argument type (which is reference type in this case, seeupdate()). So we need to wrap the arguments that really needs to be references in std::ref.
std::ref does not make a reference, so in your code sample it doesn't do what you expect. std::ref creates an object that behaves similarly to a reference. It may be useful, for example, when you want to instantiate a functor, and pass a reference-like version of it to a standard library algorithm. Since algorithms take functors by value, you can use std::ref to wrap the functor.
make_tuple(0, a) makes a tuple<int, A>.
make_tuple(0, ref(a)) makes a tuple<int, reference_wrapper<A>>.
You can also say tuple<int, A&> t(0, a); for a tuple you can't make with make_tuple, or use std::tie.
Answering the question in the title (When is the use of std::ref necessary?): Another case where std::ref is useful is when looping over a list of references to objects and modify them:
std::vector<int> v1, v2;
void test() {
for (std::vector<int>& vv :
// Compiles
{ std::ref(v1), std::ref(v2) }
// Compiler rejects this with:
// binding reference of type 'vector<...>' to value of
// type 'const vector<...>' drops 'const' qualifier
// { v1, v2}
) {
vv.push_back(3);
}
}
Without using std::ref in the list, the objects are treated as const and can't be modified (see also https://godbolt.org/z/Ta6YM31KM).