This compiles:
std::vector<int> value = boost::assign::list_of(1)(2);
But not this:
Constructor(std::vector<int> value)
{
}
Constructor (boost::assign::list_of(1)(2));
Is there a one-liner solution for initializing the vector passed to the constructor?
Better still, if the constructor copies to a class variable by taking a reference instead:
Constructor(std::vector<int>& value)
{
_value = value;
}
UPDATE
If I try the following:
enum Foo
{
FOO_ONE, FOO_TWO
};
class Constructor
{
public:
Constructor(const std::vector<Foo>& value){}
};
Constructor c(std::vector<Foo>(boost::assign::list_of(FOO_ONE)));
I get the compiler error:
error C2440: '<function-style-cast>' : cannot convert from 'boost::assign_detail::generic_list<T>' to 'std::vector<_Ty>'
1> with
1> [
1> T=Foo
1> ]
1> and
1> [
1> _Ty=Foo
1> ]
1> No constructor could take the source type, or constructor overload resolution was ambiguous
This is a annoying problem, we also had some time before. We fixed it by using the convert_to_container method:
Constructor c(boost::assign::list_of(1)(2).convert_to_container<std::vector<int> >() );
There are more issues with std::list using in constructor too. See Pass std::list to constructor using boost's list_of doesn't compile for the appropriate answer.
I'm using this template to make temporary instance of std::vector in-place:
#include <vector>
namespace Util {
//init vector
template <typename ELEMENT_TYPE > struct vector_of
: public std::vector<ELEMENT_TYPE>
{
vector_of(const ELEMENT_TYPE& t)
{
(*this)(t);
}
vector_of& operator()(const ELEMENT_TYPE& t)
{
this->push_back(t);
return *this;
}
};
}//namespace Util
Usage would look like this:
Constructor (Util::vector_of<int>(1)(2));
Constructor signature would look like this:
Constructor(const std::vector<int>& value)
{
_value = value;
}
Related
While creating a subclass of a template class I noticed I got an error on an overloaded function.
This compiler error was correct since one of the overloads was using a copy and the type was not copyable.
However, I was not using that function (correct overload or not). So I was surprised to get this error
After searching around a bit and reproducing in godbolt the culprit seemed to be __declspec(dllexport).
Reproduction in godbolt
Removing the declspec seems to result in the correct compilation.
Code in godbolt:
#include <memory>
#include <vector>
using namespace std;
template<class V>
struct Foo{
void update(const V& v);
void update(V&& v);
std::vector<V> values;
};
template<class V>
void Foo<V>::update(const V& v)
{
values[0] = v;
}
template<class V>
void Foo<V>::update(V&& v)
{
values[0] = std::move(v);
}
struct __declspec(dllexport) Bar : public Foo<std::unique_ptr<int>>
{
};
int main()
{
Bar f;
auto i = std::make_unique<int>(5);
//f.update(i);
//f.update(std::move(i));
}
My questions are mostly, how is declspec causing this behavior?
And, is there anything that can be done about this in the template class or derived class?
Error log:
(19): error C2280:
'std::unique_ptr>
&std::unique_ptr>::operator =(const
std::unique_ptr> &)': attempting to
reference a deleted function with [
_Ty=int ] C:/data/msvc/14.16.27023.1/include\memory(2338): note: see declaration of
'std::unique_ptr>::operator =' with
[
_Ty=int ] C:/data/msvc/14.16.27023.1/include\memory(2338): note: 'std::unique_ptr>
&std::unique_ptr>::operator =(const
std::unique_ptr> &)': function was
explicitly deleted with [
_Ty=int ] (18): note: while compiling class template member function 'void
Foo>>::update(const V &)'
with [
_Ty=int,
V=std::unique_ptr> ] (29): note: see reference to class template instantiation
'Foo>>' being compiled
with [
_Ty=int ]
I'm trying to make a for_each function for a generic object that uses an size function and an item index function. But I'm having some difficulty with the syntax.
This is what I have so far (starting at line 128):
class base1
{
protected:
std::vector<int> items;
public:
base1()
: items({1,2,3})
{
}
int GetCount() const
{
}
};
class base2 : public base1
{
public:
base2()
: base1()
{
}
int GetItem(int i) const
{
return items[i];
}
};
class derived : public base2
{
public:
derived()
: base2()
{
}
};
template <typename CONTAINER, typename CONTAINER_BASE1, typename CONTAINER_BASE2, typename SIZE, typename CONTAINED, typename FUNC>
void for_each(CONTAINER* container, SIZE (CONTAINER_BASE1::*GetSize)() const, CONTAINED (CONTAINER_BASE2::*GetItem)(SIZE) const, FUNC& body)
{
for (SIZE i = 0; i < container->*GetSize(); ++i)
{
body(container->*GetItem(i));
}
}
void fn()
{
derived x;
for_each(&x, &derived::GetCount, &derived::GetItem, [](int i){
++i;
});
}
Right now, I get an error from VC++ 2013 stating:
1>d:\projects\test\test.cpp(169): error C2064: term does not evaluate to a function taking 0 arguments
1> d:\projects\test\test.cpp(180) : see reference to function template instantiation 'void for_each<derived,base1,base2,int,int,fn::<lambda_862ea397905775f7e094cde6fe9b462c>>(CONTAINER *,SIZE (__thiscall base1::* )(void) const,CONTAINED (__thiscall base2::* )(SIZE) const,FUNC &)' being compiled
1> with
1> [
1> CONTAINER=derived
1> , SIZE=int
1> , CONTAINED=int
1> , FUNC=fn::<lambda_862ea397905775f7e094cde6fe9b462c>
1> ]
1>d:\projects\test\test.cpp(171): error C2064: term does not evaluate to a function taking 1 arguments
Any ideas as to what the problem is?
You have two bugs. You take the functor by non-const lvalue reference - FUNC& body - which doesn't bind to a temporary like a lambda; this was hidden by a terrible MSVC extension that allows such bindings. You should accept the function object by value (the way it is usually done by the standard library), by const lvalue reference (if copying is expensive and/or identity is important), or by forwarding reference (if identity is important and operator() can be non-const).
Second is operator precedence. The postfix function call operator has higher precedence than .* and ->*. container->*GetSize() is container->*(GetSize()); you want (container->*GetSize)().
I'm also not sure about this design. It's probably better to provide a uniform interface, and simply do, e.g., container.size() and container.at(i) than using this tortured system of pointer-to-member-functions.
I don't understand why this doesn't work (Visual C++ 2012):
#include <string>
#include <utility>
#include <vector>
#include <boost/assign/list_of.hpp>
using namespace std;
int main()
{
pair<string, vector<string> >("^", boost::assign::list_of<string>("rules"));
}
The error is:
include\utility(138) : error C2668: 'std::vector<_Ty>::vector' : ambiguous call to overloaded function with [ _Ty=std::string ]
include\vector(786): could be 'std::vector<_Ty>::vector(std::vector<_Ty> &&)' with [ _Ty=std::string ]
include\vector(693): or 'std::vector<_Ty>::vector(unsigned int)' with [ _Ty=std::string ]
while trying to match the argument list '(boost::assign_detail::generic_list<T>)' with [ T=std::string ]
test.cpp(12) : see reference to function template instantiation 'std::pair<_Ty1,_Ty2>::pair<const char(&)[2],boost::assign_detail::generic_list<T>>(_Other1,_Other2 &&,void **)' being compiled
with
[
_Ty1=std::string,
_Ty2=std::vector<std::string>,
T=std::string,
_Other1=const char (&)[2],
_Other2=boost::assign_detail::generic_list<std::string>
]
test.cpp(12) : see reference to function template instantiation 'std::pair<_Ty1,_Ty2>::pair<const char(&)[2],boost::assign_detail::generic_list<T>>(_Other1,_Other2 &&,void **)' being compiled
with
[
_Ty1=std::string,
_Ty2=std::vector<std::string>,
T=std::string,
_Other1=const char (&)[2],
_Other2=boost::assign_detail::generic_list<std::string>
]
I can't decipher why it's trying to access an unsigned int overload... any ideas?
This is because a new pair constructor was added in C++11 to accept universal references. As a result, this code will fail in VS2012 (which added this constructor) and in GCC when in C++11 mode.
In C++03:
The pair<T1,T2> constructor was:
pair( const T1& x, const T2& y ) : first(x), second(y) {}
In this case, T2 == vector<string>.
A generic_list object (the object returned by list_of) has a template conversion operator:
template <class Container>
operator Container() const;
When you pass in generic_list as a parameter, it tries to convert the generic_list object to a vector<string>, since that is what the constructor expects, and this succeeds.
In C++11:
This pair<T1,T2> constructor was added:
template< class U1, class U2 >
pair( U1&& x, U2&& y ) : first(std::forward<U1>(x)), second(std::forward<U2>(y))
Now when you pass in a generic_list object, it will be passed in as generic_list&&. When it tries to call the second (of type vector<string>) constructor with this object, it doesn't know which of these constructors to call:
explicit vector(size_type count, [more params with default values])
vector(const vector& other);
Since generic_list can be converted to both size_type and vector<string>. This results in the compilation error.
Fix/Workaround:
A possible fix is to use the convert_to_container method and specify the target type:
pair<string, vector<string> >("^", boost::assign::list_of<string>("rules").convert_to_container<vector<string> >());
Another option is to use make_pair and explicitly specify its template parameters.
So instead of this:
("^", boost::assign::list_of<string>("rules"))
I have to write:
("^", boost::assign::list_of<string>("rules").convert_to_container<vector<string> >());
Makes it kind of unreadable ...
I added Yet Another template:
template <typename T>
std::vector<T> vect(const boost::assign_detail::generic_list<T>& gen_list)
{ return gen_list.convert_to_container<std::vector<T> >(); }
and can write it now as:
("^", vect(boost::assign::list_of<string>("rules")))
which is still not nice, but closer to what you started with.
I am working on a homework assignment where we aren't allowed to use any STL containers. My implementation of LinkedList is a collection of Nodes that are chained together with pointers. I have another class called ContinuousList which has a data member LinkedList whose Nodes contain pointers to Nodes in various other LinkedLists. I'm trying to assign the return value of a function that returns a pointer to a Node to a variable that is also a pointer to a Node, but it is saying that is invalid and I don't understand why I can't do that.
template <typename ValueType>
struct Node
{
Node();
std::string m_key;
ValueType m_value;
Node<ValueType>* m_next;
};
The linked list class:
template <typename ValueType>
class LinkedList
{
public:
Node<ValueType>* begin()
{
return m_head;
}
private:
Node<ValueType>* m_head;
};
ContinuousList:
template <typename ValueType>
class ContinuousList
{
public:
ValueType* iterate(std::string& key)
{
m_curr = m_collection.begin(); // Error occurs here
...
}
private:
LinkedList<Node<ValueType>*> m_collection;
Node<ValueType>* m_curr;
};
Full error message
1> error C2440: '=' : cannot convert from 'Node<ValueType> *' to 'Node<ValueType> *'
1> with
1> [
1> ValueType=Node<bool> *
1> ]
1> and
1> [
1> ValueType=bool
1> ]
1> Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
1> while compiling class template member function 'bool *ContinuousList<ValueType>::iterate(std::string &)'
1> with
1> [
1> ValueType=bool
1> ]
1> see reference to class template instantiation 'ContinuousList<ValueType>' being compiled
1> with
1> [
1> ValueType=bool
1> ]
LinkedList<Node<ValueType>*> m_collection;
this
is making m_head be
Node<Node<ValueType>*>*
Which is not what you want.
m_curr = m_collection.begin()
Node<ValueType> = Node<Node<ValueType>*>*
if
Node<Node<ValueType>*>*
was what you wanted, use
m_collection.begin()->m_value;
or use
LinkedList<ValueType>,
and it will return Node
Though I may just be really tired.... =D
The error message I get from GCC is:
cannot convert ‘Node<Node<int>*>*’ to ‘Node<int>*’ in assignment
which is slightly clearer than the nonsense your compiler gives.
m_collection contains nodes wrapped in nodes. Depending on what you're planning to do with it, perhaps it should just be LinkedList<ValueType>, or perhaps the assignment should be m_curr = m_collection.begin()->m_value.
Also, ContinuousList::iterate should almost certainly take its argument by const reference.
In LinkedList definition you assume ValueType to be a Node parameter, but in ContinuousList you give Node<ValueType> as a LinkedList template parameter:
template <typename ValueType>
class ContinuousList
{
// (...)
LinkedList<Node<ValueType>*> m_collection;
Node<ValueType>* m_curr;
};
so your LinkedList actually looks like:
template <typename ValueType>
class LinkedList
{
public:
Node<Node<ValueType> >* begin()
{
return m_head;
}
private:
Node<Node<ValueType> >* m_head;
};
and this is obvioulsy not valid when you want to do this:
/*Node<ValueType>* */ m_curr = /* Node<Node<ValueType> >* */ m_collection.begin();
I'm constructing a simple container class but run into some problems (reassembling the ones in Visual C++ 2010, rvalue reference bug?)
#include <cassert>
#include <utility>
template<typename T0>
class MyType {
public:
typedef T0 value_type;
// Default constructor
MyType() : m_value() {
}
// Element constructor
explicit MyType(const T0 &c_0) : m_value(c_0) {
}
template<typename S0>
explicit MyType(S0 &&c_0) : m_value(std::forward<S0>(c_0)) {
}
// Copy constructor
MyType(const MyType &other) : m_value(other.m_value) {
}
MyType(MyType &&other) : m_value(std::forward<value_type>(other.m_value)) {
}
// Copy constructor (with convertion)
template<typename S0>
MyType(const MyType<S0> &other) : m_value(other.m_value) {
}
template<typename S0>
MyType(MyType<S0> &&other) : m_value(std::move(other.m_value)) {
}
// Assignment operators
MyType &operator=(const MyType &other) {
m_value = other.m_value;
return *this;
}
MyType &operator=(MyType &&other) {
m_value = std::move(other.m_value);
return *this;
}
template<typename S0>
MyType &operator=(const MyType<S0> &other) {
m_value = other.m_value;
return *this;
}
template<typename S0>
MyType &operator=(MyType<S0> &&other) {
m_value = std::move(other.m_value);
return *this;
}
// Value functions
value_type &value() {
return m_value;
}
const value_type &value() const {
return m_value;
}
private:
template<typename S0>
friend class MyType;
value_type m_value;
};
int main(int argc, char **argv) {
MyType<float> t1(5.5f);
MyType<double> t2(t1);
return 0;
}
The above code gives the following error:
1>ClCompile:
1> BehaviorIsolation.cpp
1>behaviorisolation.cpp(18): error C2440: 'initializing' : cannot convert from 'MyType<T0>' to 'double'
1> with
1> [
1> T0=float
1> ]
1> No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
1> behaviorisolation.cpp(78) : see reference to function template instantiation 'MyType<T0>::MyType<MyType<float>&>(S0)' being compiled
1> with
1> [
1> T0=double,
1> S0=MyType<float> &
1> ]
1>behaviorisolation.cpp(18): error C2439: 'MyType<T0>::m_value' : member could not be initialized
1> with
1> [
1> T0=double
1> ]
1> behaviorisolation.cpp(73) : see declaration of 'MyType<T0>::m_value'
1> with
1> [
1> T0=double
1> ]
1>
1>Build FAILED.
How can one remedy this error without using tricks like the ones described in the linked question?
Thanks!
Edit:
What confuses me the most is why isn't any of the two specialized constructors called. They fit the call a lot better.
// Copy constructor (with convertion)
template<typename S0>
MyType(const MyType<S0> &other) : m_value(other.m_value) {
}
template<typename S0>
MyType(MyType<S0> &&other) : m_value(std::move(other.m_value)) {
}
Your linked question already answers this. Let's define
typedef MyType<float> MF;
typedef MyType<double> MD;
When you say MD t2(t1);, you would like to call the constructor MF::MF(const MD &). However, the constructor template <typename T> MF::MF(T&&) matches better, because it takes T = MD& and thus resolves to MF::MF(MD&), which is a better match due to the absence of const.
To resolve this, you should essentially get rid of the MF(T&&) constructor, as Howard suggested already. Since you only intend that constructor for values anyway, my first suggestion would be to change the signature to MF(const T &), which would already solve your problem. Another solution would be to add a constructor with signature MF(MD&) (non-const). That's ugly, though. Finally, you could call the constructor explicity at the call site: MD t2(MF(t1)), or MD t2(std::forward<MF>(t1)) or even MD t2(std::move(t1)), if that's an option.
Finally note that if you are only dealing with primitive members, there's nothing to be gained from explicit moves, so you might as well not bother defining all those constructors separately.
Your constructor:
template<typename S0>
explicit MyType(S0 &&c_0)
is overly generic and the best way to solve your problem is to restrict the type which can be deduced as S0. This is basically what the linked answer does to. But perhaps I can make it prettier for you.
Here it is, in std::C++11:
template<typename S0,
class = typename std::enable_if
<
std::is_convertible<S0, T0>::value
>::type>
explicit MyType(S0 &&c_0) : m_value(std::forward<S0>(c_0)) {
}
If that is just too ugly, you might consider:
#define restrict_to(x...) class = typename std::enable_if<x>::type
...
template<typename S0, restrict_to(std::is_convertible<S0, T0>::value)>
explicit MyType(S0 &&c_0) : m_value(std::forward<S0>(c_0)) {
}
Note that this will not only solve your problem, but if your clients subsequently ask questions like:
std::is_convertible<X, MyType<T>>::type
they will now get the correct answer. As you currently have it coded, the above trait always answers true.