How do i use 'auto' in C++ (C++0x)? - c++

What do i have to do to this code to make it compile, it's braking around this line:
auto val = what.getObject();
#include<iostream>
using namespace std;
class CUP{
public:
void whatsHappening(){}
};
class MUG{
public:
void whatsHappening(){}
};
class CupThrower{
public:
CUP cp;
CUP getObject(){ return cp;}
};
class MugThrower{
public:
MUG mg;
MUG getObject(){return mg;}
};
template <typename T> void whatsHappening(T what){
auto val = what.getObject(); //DOES NOT COMPILE
val.whatsHappening();
}
int main(){
CupThrower ct;
MugThrower mt;
whatsHappening(ct);
whatsHappening(mt);
return 0;
}
i am using VS2008 to compile.

Auto isn't supported in VS2008. Use VS2010 and later versions, or another compiler supporting this feature.

Others have said that auto isn't in VC9, which is sort-of true. auto doesn't mean in the current C++ Standard what it means in C++0x. In the current Standard, it effectively means nothing useful. Long story short, you can't use auto the way you're trying to use it here.
But there is an alternative. In this code:
template <typename T> void whatsHappening(T what){
auto val = what.getObject(); //DOES NOT COMPILE
val.whatsHappening();
}
...the problem you're having is val is of an unknown type. If T is CupThrower, then getObject() returns a CUP. Likewise, for MugThrower, getObject() returns a MUG. The way your code is written, you have no way to know the type returned by getObject() based solely on the type of T. So the solution is to add a way to know it. Try this:
class CupThrower{
public:
typedef CUP ObjectType;
ObjectType cp;
ObjectType getObject(){ return cp;}
};
class MugThrower{
public:
typedef MUG ObjectType;
ObjectType mg;
ObjectType getObject(){return mg;}
};
Now the type returned by getObject() is part of the enclosing class. You can change your whatsHappening() function to use this information:
template <typename T> void whatsHappening(T what){
T::ObjectType val = what.getObject(); //DOES COMPILE!
val.whatsHappening();
}
And all is right with the world again.

Auto is a feature only present in C++0x and, therefore, isn't enabled by default in most (if not all) the compilers. Have you used the appropriate options in your compiler to enable it?

It doesn't compile because you're trying to deal with zero-sized non-function objects.
Edit:
Works fine for me in VS2010.

Related

How to use Objective-C sources' ExplicitInit class?

In the Objc source code, I found the following code. What is the meaning of this code and how to understand it?
objc/Project Headers/DenseMapExtras.h line:38
template <typename Type>
class ExplicitInit {
alignas(Type) uint8_t _storage[sizeof(Type)];
public:
template <typename... Ts>
void init(Ts &&... Args) {
new (_storage) Type(std::forward<Ts>(Args)...);
}
Type &get() {
return *reinterpret_cast<Type *>(_storage);
}
};
Below is my test code:
class MyC{
public:
long l1;
long l2;
MyC(long _l1, long _l2){
l1 = _l1;
l2 = _l2;
}
};
int main(){
MyExplicitInit<MyC> e1 {};
e1.init();
return 0;
}
The compiler prompts the following error:
In the Objc source code, I found the following code. What is the
meaning of this code and how to understand it?
To me it looks like a kind-of-factory which can be used as an alternative to the Construct On First Use Idiom. An instantiated class here represents a storage for an instance you can initialise and request when needed. As far as I understand it's not supposed to be used for local variables (it doesn't make much sense, despite being technically possible) and this is also suggested by the comments of code section with the said class template:
// We cannot use a C++ static initializer to initialize certain globals because
// libc calls us before our C++ initializers run. We also don't want a global
// pointer to some globals because of the extra indirection.
//
// ExplicitInit / LazyInit wrap doing it the hard way
For the error you are experiencing:
No matching operator new function for non-allocating placement new expression;
include <new>
Assuming that you just added that piece of code somewhere in your own sources, the problem here is that you didn't include the <new> header. As simple as that - the error just says that you need to add #include <new> since so-called placement new is not part of the "default" C++, it's an overloaded operator declared in this header.
Second, your init function expects arguments that matches one of the existing (non-aggregate) constructors of the given class, so you are expected to pass arguments which are either match the constructor parameters or can be implicitly converted to them: e1.init(1l, 2l)
A complete example looks something like this:
#include <_types/_uint8_t.h>
#include <new>
namespace objc {
template <typename Type>
class ExplicitInit {
alignas(Type) uint8_t _storage[sizeof(Type)];
public:
template <typename... Ts>
void init(Ts &&... Args) {
new (_storage) Type(std::forward<Ts>(Args)...);
}
Type &get() {
return *reinterpret_cast<Type *>(_storage);
}
};
};
struct sample_struct {
long l1, l2;
sample_struct(long _l1, long _l2): l1{_l1}, l2{_l2} {}
};
sample_struct& getInstance(bool should_init = false) {
static objc::ExplicitInit<sample_struct> factory;
if (should_init) {
factory.init(1l, 2l);
}
return factory.get();
}

MSVC failed to compile when converting a base type to a derived type in a constant-expression

Code:
#include <cstddef>
template <typename value_type, typename iterator_type>
class array_iterator_base
{
protected:
value_type *ptr;
public:
constexpr array_iterator_base() : ptr(nullptr) {}
constexpr iterator_type &operator++()
{
++ptr;
return *static_cast<iterator_type *>(this); // [1]
}
};
template <typename value_type>
class array_iterator : public array_iterator_base<value_type, array_iterator<value_type>>
{
public:
constexpr array_iterator(value_type *ptr)
{
this->ptr = ptr;
}
};
template <typename value_type, std::size_t Size>
class array
{
public:
using iterator = array_iterator<value_type>;
value_type m_data[Size];
constexpr iterator begin() { return iterator(m_data); }
};
class Demo
{
using storage = array<int, 3>;
using iterator = typename storage::iterator;
private:
storage m_arr = { 1, 2, 3 };
iterator m_iter = m_arr.begin();
public:
constexpr Demo() {}
constexpr void field()
{
++m_iter; // MSVC: failed
}
constexpr void local_variable()
{
storage arr = { 1,2,3 };
iterator iter = arr.begin();
++iter; // MSVC: OK
}
};
constexpr int ok()
{
Demo demo;
demo.local_variable();
return 1;
}
constexpr int error()
{
Demo demo;
demo.field();
return 1;
}
int main()
{
constexpr int x = ok();
// GCC: OK
// Clang: OK
// MSVC: OK
constexpr int y = error(); // [2]
// GCC: OK
// Clang: OK
// MSVC: error
}
Error at line [2] due to line [1]:
Expression did not evaluate to a constant.
Failure was caused by cast of object of dynamic type
array_iterator<value_type>
to type
iterator_type
with
[value_type=int]
[iterator_type=array_iterator<int>]
I am writing an array class myself. I decide to write an array iterator base class so that any array iterator class can just inherit from it to save some keystrokes. To do this, I must cast the base class to the derived iterator class when there is a need to return the iterator itself, so there is the return *static_cast<iterator_type *>(this); in the iterator_type &operator++() overload.
However, in a constexpr context, MSVC failed to compile when the iterator is a field in a class but compiled successfully when the iterator is a local variable. The error message said that the expression is not constant because the function call involves casting a dynamic type (see above).
GCC and Clang compiled successfully in both cases.
Interestingly, in Visual Studio, the value of y can actually be previewed (by hovering the cursor on it) just like any other constexpr variable (which makes me think that MSVC is probably wrong).
Edit: The latest preview version of MSVC still does not compile.
Edit: I have reported this bug to Microsoft here.
Questions:
Which compiler is correct according to the standard?
Is there a better way to do what I am doing (i.e. writing a base class for iterator classes to inherit from)?
I don't see any reason that this shouldn't compile.
MSVC's error message makes no sense, because array_iterator<value_type> with value_type = int is array_iterator<int> and iterator_type is also array_iterator<int>. So the cast is valid.
this also refers an object that was created in this constant expression evaluation that started with the call to error(), so there is no reason to reject it as subevaluation of the constant expression.
Both GCC and Clang seem to agree with that analysis, so it is likely a MSVC bug. I also don't see any problem with the CRTP you are using here. I don't see the benefit though, since as it is there is only one class definition( array_iterator) inheriting from the CRTP base.
Downcasting seems appropriate. You only have to make sure that an instance of type array_iterator_base is never directly created. You could e.g. make the constructors of array_iterator_base protected to achieve that.

I need a non template solution

I have a class defined like this
class A
{
private:
map<int,vector<int>> m;
public:
vector<int> GetJsonVal(int k)
{
return m[k];
}
};
I would like to change it into something like this
template<class T>
class A
{
private:
map<int,T> m;
public:
T GetJsonVal(int k)
{
return m[k];
}
};
However, I have many other places that plainly use only type A, so if I change my class into the latter, I have to fix a lot i.e change all into A<type>, which I don't want. In those places I simply do void func(A*p) or A& r=....
So, how can I both use i.e A<float> and A anywhere I like ?
So, the easiest and most legible solution that comes to mind is a type alias:
template <typename T>
class Tool {
private:
map<int,vector<T>> m;
public:
vector<T> GetJsonVal(int k) {
return m[k];
}
};
using A = Tool<int>;
And so now the old code can continue using A, and all new code can use Tool<int> or another type alias.
You could use type-erasue, but will still need to update the code here and there... An approach could be doing something like:
class A {
map<int, boost::any> m;
template <typename T>
T valueAs(int idx);
};
A a;
a.valueAs<int>();
You would have the implementation verify that the type stored and the type retrieved are the same. Then you would probably want to go to all existing uses of A and enforce the check (or check the potential error).
That is, if you want to support mixed types inside A... if you each A can only hold a particular type, you can just make a ATmpl type with the contents in the question, and then typedef ATmpl<vector<int>> A;. At this point you would still have to fix some use cases (specifically: forward declarations)...
Use template class specialization, I would say
template <> class A<vector<int>>
{
// all your old code here
}
should work...
UPDATE
Just to be clear, there is a semantic difference between template specialization and type alias. With template specialization you could put your (true and tested and bug-for-bug compatible) code into specialization and use new and shiny (but potentially buggy code) elsewhere in new production, and later when you fill it is good enough you could remove specialization and use only new code. With type specialization it is new code everywhere right away...

gcnew operator for generic type

I have the following simple class
generic<typename T> where T:IDbConnection ref class CDbConnection
{
private:
IDbConnection^m_db;
ConnectionState^ m_originalConnState;
public:
CDbConnection();
bool Connect(String ^ connStr);
bool Exists(int id);
auto GetAllData(String^ tableStr);
~CDbConnection();
!CDbConnection();
};
and here is my constructor
generic<typename T> CDbConnection<T>::CDbConnection()
{
m_db=gcnew T();
m_originalConnState=m_db->State;
}
But the compiler complains <1> the gcnew T() can't be used for generic type
<2> auto key in use is wrong as the function expects a trailing return type
Thank you for your reading and replies
I forgot this
where T:IDbConnection, gcnew()
which is exactly the same as C# generics
to get rid of the gcnew error as stated above.
In order to achieve genericity, you must change your class definition to
generic<typename T> where T:IDbConnection ref class CDbConnection
{
private:
T m_db;
ConnectionState^ m_originalConnState;
public:
CDbConnection();
bool Connect(String ^ connStr);
bool Exists(int id);
auto GetAllData(String^ tableStr);
~CDbConnection();
!CDbConnection();
};
As you are already constraining your T to be at least IDbConnection it can't be anything else.
Then your constructor
generic<typename T> CDbConnection<T>::CDbConnection()
{
m_originalConnState=m_db.State;
}
should work like you intended.
EDIT
It seems you cannot declare a reference to a generic. If you assign the object to the stack it will work.
See this entry.
// C3229.cpp
// compile with: /clr /c
generic <class T>
ref class C {
T^ t; // C3229
};
// OK
generic <class T>
ref class D {
T u;
};

Checking a member exists, possibly in a base class, VS2005/08 version

In Checking a member exists, possibly in a base class, C++11 version, we developed a C++11 version of the classical member-checking type-trait from SFINAE to check for inherited member functions that also works with C++11 final classes, but uses C++11 features (namely, decltype), too:
template<typename T>
class has_resize_method {
struct Yes { char unused[1]; };
struct No { char unused[2]; };
static_assert(sizeof(Yes) != sizeof(No));
template<class C>
static decltype(std::declval<C>().resize(10), Yes()) test(int);
template<class C>
static No test(...);
public:
static const bool value = (sizeof(test<T>(0)) == sizeof(Yes));
};
MSVC has had final as a non-standard extension named sealed since VS2005, but decltype has only been added in VS2010. That leaves VS2005 and 2008 where a class that is marked as sealed still breaks the classical type-trait and the C++11 version cannot be used.
So, is there a way to formulate has_resize_method such that it works on VC2005/08 sealed classes, too?
Obviously, just as using C++11-only features to work around a C++11-only problem (final) is fine, so would be using VS-only extensions to work around the VS2005/08-only problem of sealed classes, but if there's a solution that works for all three sets of compilers {C++11,{VS2005,VS2008},all others}, that would be cool, but probably too much to ask for :)
I was able to come up with a solution that works in all major compilers. Sadly, there is a preprocessor check for MSVC because it complains about the solution for other compilers. The main difference is that MSVC does not accept function pointers inside sizeof() and conversely, GCC does not seem to accept (&C::resize == 0) in the check. Clang happily accepts both.
#include <iostream>
class Base {
public:
void resize(int, int, int) { }
};
class Derived : public Base {
};
class Unrelated { };
template<typename T>
class has_resize_method {
struct Yes { char unused[1]; };
struct No { char unused[2]; };
#ifdef _MSC_VER
template <class C>
static Yes test(char (*)[(&C::resize == 0) + 1]);
#else
template <class C>
static Yes test(char (*)[sizeof(&C::resize) + 1]);
#endif
template<class C>
static No test(...);
public:
static const bool value = (sizeof(test<T>(0)) == sizeof(Yes));
};
int main() {
std::cout << (has_resize_method<Base>::value ? "Base has method resize" : "Base has NO method resize") << std::endl;
std::cout << (has_resize_method<Derived>::value ? "Derived has method resize" : "Derived has NO method resize") << std::endl;
std::cout << (has_resize_method<Unrelated>::value ? "Unrelated has method resize" : "Unrelated has NO method resize") << std::endl;
return 0;
}
Output:
Base has method resize
Derived has method resize
Unrelated has NO method resize
Tested on GCC 4.5.3, GCC 4.3.4, Clang 3.0, Visual C++ 2008 and Visual C++ 2010. I don't have access to Visual C++ 2005 but I think it will work there, too. It also compiles on Comeau Online but I cannot guarantee it produces a correct output there.
Works with both final and __sealed classes.
Note though that it checks not only for member functions but for member pointers in general. You might want to add additional checks such as boost::is_member_function_pointer if this behavior is unwanted. Similarly, you might want to add checks for number of arguments/argument types/result types - again, boost will be very helpful here, esp. boost type decomposition.
MSVC has a special statement __if_exists since vs2005. MSDN Link here. You can use it to check the member function name directly. And then check the signature. Following is a simple foo detection example:
template <typename T, typename U>
int8_t FooCheck( void(T::*)(U) )
{
return 0;
}
template <typename T>
int16_t FooCheck( void(T::*)(double))
{
return 0;
}
template <typename T>
int32_t FooCheck(void(T::*)(int))
{
return 0;
}
template <typename T>
class Detector
{
public:
__if_exists(T::foo)
{
enum
{
value = sizeof(FooCheck(&T::foo))
};
}
__if_not_exists(T::foo)
{
enum
{
value = 0
};
}
};
std::cout << Detector<Class>::value << std::endl;