Strange #define in Template?
I've got a small bit of code from a li开发者_JAVA技巧brary that does this:
#define VMMLIB_ALIGN( var ) var
template< size_t M, typename T = float >
class vector
{
...
private:
// storage
VMMLIB_ALIGN( T array[ M ] );
};
And you can call it by doing
//(vector<float> myVector)
myVector.array;
No parenthesis or anything.
what?
After reading the answers, it appears I should've done more looking. XCode's "Jump to Definition" gave me only one result. Searching the library gave me another:
#ifndef VMMLIB_CUSTOM_CONFIG
# ifndef NDEBUG
# define VMMLIB_SAFE_ACCESSORS
# endif
# define VMMLIB_THROW_EXCEPTIONS
# ifdef VMMLIB_DONT_FORCE_ALIGNMENT
# define VMMLIB_ALIGN( var ) var
# else
# ifdef __GNUC__
# define VMMLIB_ALIGN( var ) var __attribute__((aligned(16)))
# elif defined WIN32
# define VMMLIB_ALIGN( var ) __declspec (align (16)) var
# else
# error "Alignment macro undefined"
# endif
# endif
#endif
This offers different settings, depending on what system it's building for.
Regardless, thanks. Can't believe I got confused over a member access!
Ultimately, myVector.array
refers to the array variable in the class, and variables don't need the function-calling notation ()
.
BTW / all-capital identifiers should only be used for preprocessor macros (as they are here). In this case, the macro VMMLIB_ALIGN
must be being used to make it easier to later "enchance" the code generated for and alongside the array
variable (e.g. prefixing it with static, extern, const, volatile or something compiler-specific) and/or adding some associated functionality such as get/set/search/clear/serialise functions that work on the array.
In general - when you're not sure what the macro is doing, you can get more insight by running the compiler with a command-line switch requesting preprocessor output (in GNU g++, the switch is -E
)... then you'll be able to see the actual source code that the C++ compiler proper deals with.
EDIT - few thoughts re your comment, but too long to include in a comment of my own...
C++ classes are private until another access specifier is provided (but in practice the public interface is normally put first so the programmer still must remember to explicitly use private
). structs are public by default. So, data is effectively exposed by default in the most common coding style. And, it doesn't need functional-call semantics to access it. Objective-C may well be better at this... your comment implies you use functional call notation for data members and functions, which is hidden by default? It's so good to have a common notation! In C++, the difficult case is where you have something like...
struct Point
{
double x, y;
};
...
// client usage:
this_point.x += 3 - that_point.y;
...then want to change to...
struct Point
{
double angle, distance;
};
...you'd need some pretty fancy and verbose manually-coded and not terribly efficient proxy objects x and y to allow the old client code to keep working unmodified while calculating x and y on the fly, and updating angle and distance as necessary. A unified notation is wonderful - allowing implementation to vary without changes to client source code (though clients would need to recompile).
maybe I'm oversimplying, but if you look at the #define macro it just writes the variable into the class.
So you have
class vector
{
...
T array[ M ];
};
after the expansion. So it's just a public variable on your class.
array
is not a method, it's an array of type T
of size M
.
First, for the record, templates have nothing to do with this. There is no special interaction between the macro and the fact that your class is a template.
Second, going by the name of the macro, I'd guess it is meant to ensure alignment of a variable.
That is, to get an aligned instance x
of a type X
, you'd use VMMLIB_ALIGN(X x);
In practice, the macro does nothing at all. It simply inserts its argument, so the above results in the code X x;
and nothing else.
However, it may be that the macro is defined differently depending on the hardware platform (since alignment requirements may vary between platforms), or over time (use a dummy placeholder implementation like this early on, and then replace it with the "real" implementation later)
However, it does seem pointless since the compiler already ensures natural alignment for all variables.
精彩评论