To save some space in my code, I made this typedef:
typedef clients.members.at(selectedTab) currentMember;
however, g++ gives me this error:
error: expected initializer before '.' token
I figure that I'm misusing typedef, since clients.members.at(selectedTab) is a function call and not a type. Is there a way to do what I'm trying to do here?
If this is used function-local and neither clients.members nor selectedTab change between its uses, just use references. E.g.:
Member& currentMember = clients.members.at(selectedTab);
currentMember.foo();
currentMember.bar();
You seem to be trying to create a macro.
#define currentMember clients.members.at(selectedTab)
Though depending on how it's used, a simple function could be much better.
In C++0x, you can do
decltype(clients.members.at(selectedTab)) currentMember(clients.members.at(selectedTab));
However, what you're doing is fundamentally not possible. You're trying to get a value and make it a type. That's just not doable. Consider the following code:
typedef clients.members.at(selectedTab) currentMember;
currentMember a;
What on earth is a, and what does it do? You're going to have to explain more what you want.
Related
I have two enum class types: Type and SocketType. The following code won't compile and fails with the message mentioned in the question, in VC++ 2017:
static constexpr std::map<Type,SocketType> PacketTypeMap =
{
{Type::JUSTJOINED, SocketType::TCP},
{Type::CHAT_MESSAGE, SocketType::TCP},
{Type::REQUEST_WORLD, SocketType::TCP},
{Type::DATA_WORLD, SocketType::TCP},
{Type::DATA_PLAYER, SocketType::UDP},
{Type::RESPAWN_PLAYER, SocketType::TCP}
};
Been trying some variations and nothing works, but I'm sure I'm just missing something simple with the syntax.
std::map is not compatible with constexpr. There exists an experimental(?) library called frozen, which provides a constexpr-compatible frozen::map (besides frozen::unordered_map, frozen::string, and others).
However, most probably you just want to pick a simpler solution (e.g., a switch statement in a constexpr function).
Migrating the answer from the comments section into the answer section.
There are no constexpr maps. It uses dynamic allocation, which is not possible with constexpr. Get rid of constexpr, or use a different container for compile-type map.
So i am currently importing a small C library into a new empty C++ project, but it simply won't compile. It works just fine compiling it with C, but it simply doesn't with C++. The only thing i am doing is including the header.
It seems to be a syntax fault, but it could be someting else. This is the only thing the compiler nags about:
error: expected unqualified-id before 'export'
bool (*export)(struct wld_exporter * exporter, struct wld_buffer * buffer, uint32_t type, union wld_object * object);
error: expected ')' before 'export'
Since i thought it was a syntax issue, i just didn't know what to do and tried stupid things like moving the asterix after export instead of prior hoping that it would work, but it obviously didn't.
I have no idea why the compiler can't recognize that it's supposed to be a function pointer, i have done function pointers c-style in c++ before without any issues.
I am using gcc and C++11 if that makes any difference.
export is a keyword in C++, you can't use it as an identifier.
List of keywords here: C++ keywords
export is a keyword in C++. You'll have to choose a different name.
What is wrong with the following "trick" for hiding unique_ptr ugliness?
class Drawable;
typedef unique_ptr<Drawable> pDrawable;
#define newDrawable(...) pDrawable(new Drawable (##__VA_ARGS__))
The first two are fine. But the third one is causing an error in VS2012:
23 IntelliSense: "std::unique_ptr<_Ty, _Dx>::unique_ptr(const std::unique_ptr<_Ty, _Dx>::
_Myt &) [with _Ty=Drawable, _Dx=std::default_delete<Drawable>]" (declared at line 1447 of
"C:\vs2012\VC\include\memory") is inaccessible file.h 36 26
I don't see why this wouldn't work, unless I am misunderstanding how C++ define macros work. I thought that it would simply replace this code:
newDrawable(a, b, c)
with
unique_ptr<Drawable>(new Drawable(a, b, c));
I understand that unique_ptr cannot be copied, but I am not copying it, here. Am I?
edit:
I have received some requests for "use" of the macro in question:
If I were to use it, it would be used as follows:
pDrawable myDraw = newDrawable();
which I would want to translate to:
unique_ptr<Drawable> myDraw = unique_ptr<Drawable>(new Drawable());
However, I cannot even compile the macro without visual studio giving the below error. It's as if something in the #define is impermissible, per se. The error is returned on the line where I make the define, not where I call the define.
See here for why make_unique doesn't work: make_unique does not compile
edit2
I have answered the question below. The code above does compile, and work.
Well, #define is, IMHO, a huge problem because it doesn't obey scoping rules and they do simple textual substitution that can sometimes have surprising results. I consider preprocessor macros to be the last resort when I need to get something done.
It would be much better to define a template like make_shared that returned a unique_ptr<T>. This is allowable because you could then move it into place.
auto a_drawable = make_unique<Drawable>(a, b, c);
template <typename T, typename... Args>
::std::unique_ptr<T> make_unique(Args&&... args)
{
return ::std::unique_ptr<T>{new T(::std::forward<Args>(args)...)};
}
That's much cleaner than the macro, and it works for any non-array type. Which is a problem. It can be made to work for array types as well, but that code is a bit more complex, and rather than repeat it, I'll just point at the answer a helpful commenter referred me to:
make_unique and perfect forwarding
As for why you're getting the error you do when you use your macro, I'm not sure. It looks like you're using your macro in some context where the result gets turned into a const ::std::unique_ptr<Drawable> &, and then tries to move construct it into a different pDrawable. This won't work. Why that's happening, I don't know. It depends crucially on the context in which you're using the macro, and you haven't provided that.
And that just highlights my first point. One reason macros are really ugly because they are simple textual substitution and their meaning can change depending on context.
Answer:
Make sure you actually use the macro, and everything will be ok.
Apparently, in an attempt to validate #define macros, VC++ checks your actual use of the macro. If there is no actual use of the macro compiled, VC++ tries to "understand" it, and can throw compiler errors.
Magically, if I add:
pDrawable myDraw = newDrawable();
After my code above, the error disappears.
Sorry for wasting everyone's time. At least this inspired me to read the following article:
http://blogs.msdn.com/b/vcblog/archive/2009/02/03/rvalue-references-c-0x-features-in-vc10-part-2.aspx
What does this define do, and how would I use it?
#define UNUSED(VAR) (void)&(VAR)
Does it require a definition anywhere? This is in the header.
edit - I don't really understand what is going on here. is this a macro'd cast to void? doesn't that negate the variable?
It exists to avoid warnings for unused parameters and variables. Simply casting to void is enough for that: it uses the variable, and the cast usually does nothing. I can only guess what the & operator is used for here. Maybe it's to prevent a conversion operator from being called. However, it doesn't prevent an overloaded operator& from being called. Or it could be to make sure it is only used on variables, but that is not perfect either: it can be used on expressions that produce references.
The intention is to prevent yourself getting a compiler warning about an unused parameter.
The better way is just to leave it anonymous, e.g.
void do_stuff( int x, int );
the 2nd parameter is unused on this case. It may need to be there for some overload purpose.
With regards to using it for a local variable - you have to ask yourself, why declare a local variable and then not use it?
Well the answer may be that you use pre-processors in the code in such a way that a variable will sometimes be used but not always. However it may not always be practical to pre-process out its existence.
The fact you declare a variable unused does not make it an error if you really do use it.
It is a macro that can be used to stop the compiler complaining/warning about a variable that is delcared but not referenced. It is common to achieve the same result with a compiler #pragma setting to disable such warnings globaly.
It's for when you have you compiler produce warnings or errors if some variable remains unused. Using a define like this, you can insert a "no-op" that silences these warnings/errors if you checked the situation.
For example:
void foo()
{
int x=0;
UNUSED(x); // don't warn me that x is not actually being used
}
Considering this answer for the benefit of typedefs on basic types and why they are used, is there any way to ensure that in your project you did not use a basic type and used the typedef counterparts?
If you really, absolutely want to ban native types but allow typedefs, I guess you can always do something like:
#include <stdint.h>
#define int please_use_stdint_typedefs_rather_than_native_types
int main()
{
int32_t good; // Good typedef.
int evil; // Evil native type.
}
$ gcc -c int_forbidden.c
int_forbidden.c: In function ‘main’:
int_forbidden.c:8: error: ‘please_use_stdint_typedefs_rather_than_native_types’ undeclared (first use in this function)
int_forbidden.c:8: error: (Each undeclared identifier is reported only once
int_forbidden.c:8: error: for each function it appears in.)
int_forbidden.c:8: error: expected ‘;’ before ‘evil’
That said, I don't think outright banning native types is a good idea in the general case.
You can make these typedefs Strong Typedefs as proposed in this boost library : http://www.boost.org/doc/libs/1_40_0/boost/strong_typedef.hpp
Considering a typedef is just a synonym for a type and does not actually create a new type, I don't think there would be any reliable way to ensure this. You could write a script to run through the code and look for occurrences of primitive types vs. the expected typedef counterpart.