I am having following code which is taken from modern C++ design. While i am using it i am getting compiation error i think invalid sizeof opearand. Can any one point out what is the problem. Thanks!
template<bool>
struct CompileTimeChecker {
CompileTimeChecker(...);
};
template<>
struct CompileTimeChecker<false> {
};
#define STATIC_CHECK(expr, msg) \
{\
class ERROR_##msg {}; \
(void)sizeof(CompileTimeChecker<(expr) != 0>((ERROR_##msg())));\
}
template <class To, class From>
To safe_reinterpret_cast(From from) {
STATIC_CHECK(sizeof(From) <= sizeof(To), Destination_Type_Too_Narrow);
return reinterpret_cast<To>(from);
}
int main(void)
{
int a[20];
void* somePointer = a;
char c = safe_reinterpret_cast<int>(somePointer);
}
Error:
d:\technical\c++study\readparsing\readparsing\addressconv.cpp(29) : error C2066: cast to function type is illegal
1> d:\technical\c++study\readparsing\readparsing\addressconv.cpp(37) : see reference to function template instantiation 'To safe_reinterpret_cast(From)' being compiled
1> with
1> [
1> To=int,
1> From=void *
1> ]
1>d:\technical\c++study\readparsing\readparsing\addressconv.cpp(29) : error C2070: 'CompileTimeChecker<__formal> (safe_reinterpret_cast::ERROR_Destination_Type_Too_Narrow (__cdecl *)(void))': illegal sizeof operand
1> with
1> [
1> __formal=true
1> ]
Yet another strike for the most vexing parse...
sizeof(CompileTimeChecker<(expr) != 0>((ERROR_##msg()))
Is the same as
class Foo {};
class Bar {};
sizeof(Foo((Var()));
and as Foo(Var) can be interpreted either as a type (function taking a (function without an argument an returning a Var) and returning a Foo), it is so.
Like AProgrammer pointed out, the (void)sizeof isn't getting swallowed by the compiler. I suggest removing the parentheses from the sizeof, like this:
(void)sizeof CompileTimeChecker<(expr) != 0>((ERROR_##msg()));\
That seems to make g++ accept it, and interpret it the way it was probably meant to.
If that (void)sizeof keeps giving you trouble, you can get the static checking functionality without it too, for example by initializing a CompileTimeChecker variable:
CompileTimeChecker<(expr) != 0> a((ERROR_##msg()));\
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 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've been butting my head against this problem in an assignment I've been working on, and can't seem to get it to work at all. I wrote a little test class to demonstrate what I'm trying to do, and hopefully someone can explain what I need to do.
//Tester class
#include <iostream>
using namespace std;
template <typename T>
class Tester
{
typedef void (Tester<T>::*FcnPtr)(T);
private:
T data;
void displayThrice(T);
void doFcn( FcnPtr fcn );
public:
Tester( T item = 3 );
void function();
};
template <typename T>
inline Tester<T>::Tester( T item )
: data(item)
{}
template <typename T>
inline void Tester<T>::doFcn( FcnPtr fcn )
{
//fcn should be a pointer to displayThrice, which is then called with the class data
fcn( this->data );
}
template <typename T>
inline void Tester<T>::function()
{
//call doFcn with a function pointer to displayThrice()
this->doFcn( &Tester<T>::displayThrice );
}
template <typename T>
inline void Tester<T>::displayThrice(T item)
{
cout << item << endl;
cout << item << endl;
cout << item << endl;
}
-and here's main:
#include <iostream>
#include "Tester.h"
using namespace std;
int main()
{
Tester<int> test;
test.function();
cin.get();
return 0;
}
-and lastly, my compiler errors (VS2010)
c:\users\name\documents\visual studio 2010\projects\example\example\tester.h(28): error C2064: term does not evaluate to a function taking 1 arguments
1> c:\users\name\documents\visual studio 2010\projects\example\example\tester.h(26) : while compiling class template member function 'void Tester<T>::doFcn(void (__thiscall Tester<T>::* )(T))'
1> with
1> [
1> T=int
1> ]
1> c:\users\name\documents\visual studio 2010\projects\example\example\tester.h(21) : while compiling class template member function 'Tester<T>::Tester(T)'
1> with
1> [
1> T=int
1> ]
1> c:\users\name\documents\visual studio 2010\projects\example\example\example.cpp(7) : see reference to class template instantiation 'Tester<T>' being compiled
1> with
1> [
1> T=int
1> ]
Hopefully, my comments in the Tester class will tell you what I'm trying to do. Thank you for taking the time to look at this!
You're not calling the member function pointer corrently; it requires the use of a special operator called the pointer-to-member operator.
template <typename T>
inline void Tester<T>::doFcn( FcnPtr fcn )
{
(this->*fcn)( this->data );
// ^^^
}
To call a member function via a pointer-to-member-function plus instance pointer, you need the ->* syntax, minding operator precedence:
(this->*fcn)(data);
You need to explicitly add the object you message:
(*this.*fcn)(this->data); // << '*this' in this case
see also the C++ FAQ
I've heard a little bit about reference-to-reference problem and this resolution. I'm not very good with C++ Committee terminology, but I understand the "Moved to DR" annotation in the link means that this is the current interpretation that standard-conforming compilers should adhere to.
I have this sample code that I can't understand:
template <typename T>
struct C {
void f(T&) { }
void f(const T&) { }
};
int main() {
C<int> x; // OK
C<int&> y; // compile error: f cannot be overloaded
C<const int&> z; // compile error: f cannot be overloaded
}
I understand the error in C<const int&> case: using rules from DR #106 we get two methods with the same signature f(const int&). What I don't get is the C<int&> case: shouldn't it generate exactly the same code as C<int> (at least according to Stroustrup's resolution)?
DR only means "Defect Report", and to my knowledge, the described resolution hasn't made it (yet) to the standard. For this reason, I believe a strictly conforming C++03 implementation should not compile this code because of it is forming a reference to a reference.
[Edit] Just found a nice answer on this issue.
Interestingly, when I compile your code (Visual C++ 10 Express) I get errors, but also when I try this simpler case:
int main(int argc, char* argv[])
{
C<int> x; // OK
C<const int> x1; // error C2535: 'void C<T>::f(T &)' : member function
// already defined or declared
return 0;
}
Seems like the ref-to-ref collapsing defined in the DR you mentioned means that const ref becomes a simple non-const ref within the template. My problem with this is that I don't understand why the second f is not just ignored.
If I change C so that the second f is const-qualified, this now compiles:
template <typename T>
struct C {
void f(T&) { }
void f(const T& t) const {}
};
The implication seems to be that when C is instantiated with const anything (ref or not), the two C::f overloads are simply identical, and result in compile-time duplicate detection.
Perhaps somebody smarter than me can decipher the chain more definitively here.
EDIT: On reflection, it's not surprising here that T = const int& results in the f overloads being identically instantiated as
void f(const int&) {}
That's what the compiler is telling me:
#include "stdafx.h"
template <typename T>
struct C {
void f(T&) { }
void f(const T&) { }
};
int main() {
C<const int&> z; // compile error: f cannot be overloaded
return 0;
}
gives this error:
1>test.cpp(6): error C2535: 'void C<T>::f(T)' : member function already
defined or declared
1> with
1> [
1> T=const int &
1> ]
1> test.cpp(5) : see declaration of 'C<T>::f'
1> with
1> [
1> T=const int &
1> ]
1> test.cpp(10) : see reference to class template instantiation
'C<T>' being compiled
1> with
1> [
1> T=const int &
1> ]
I'm not even convinced this has anything to do with the DR.