I'm trying to compile the following piece of code, I get an error on the line which specializes std::vector, it seems the one parameter being passed-in is somehow being assumed to be two parameters. Is it perhaps something to do with angle-brackets?
Is there a special way/mechanism where by such parameters can be correctly passed to the macro?
#include <vector>
template<typename A>
struct AClass {};
#define specialize_AClass(X)\
template<> struct AClass<X> { X a; };
specialize_AClass(int) //ok
specialize_AClass(std::vector<int,std::allocator<int> >) //error
int main()
{
return 0;
}
The error that I get is as follows:
1 Line 55: error: macro "specialize_AClass" passed 2 arguments, but takes just 1
2 Line 15: error: expected constructor, destructor, or type conversion before 'int'
3 compilation terminated due to -Wfatal-errors.
Link: http://codepad.org/qIiKsw4l
template<typename TypeX, typename TypeY>
class Test
{
public:
void fun(TypeX x, TypeY y)
{
std::wcout << _T("Hello") << std::endl;
std::wcout << x << std::endl;
std::wcout << y << std::endl;
}
};
#define COMMOA ,
#define KK(x) x val;
void main()
{
KK(Test<int COMMOA int>);
val.fun(12, 13);
}
I have a new way to solve this trouble. hope it can help you :)
You have two options. One of which was mentioned already: Using __VA_ARGS__. This however has the disadvantage that it doesn't work in strict C++03, but requires a sufficiently C99/C++0x compatible preprocessor.
The other option is to parenthesize the type-name. But unlike another answer claims, it's not as easy as just parenthesizing the type name. Writing a specialization as follows is ill-formed
// error, NOT valid!
template<> struct AClass<(int)> { X a; };
I have worked around this (and boost probably uses the same under the hood) by passing the type name in parentheses, and then building up a function type out of it
template<typename T> struct get_first_param;
template<typename R, typename P1> struct get_first_param<R(P1)> {
typedef P1 type;
};
With that, get_first_param<void(X)>::type denotes the type X. Now you can rewrite your macro to
#define specialize_AClass(X) \
template<> struct AClass<get_first_param<void X>::type> {
get_first_param<void X>::type a;
};
And you just need to pass the type wrapped in parentheses.
There is a couple of issues here.
First of all, macros are extremely dumb, they're complicated, but essentially amounts to a pure text replacement processus.
There are therefore 2 (technical) issues with the code you exposed:
You cannot use a comma in the middle of a macro invocation, it just fails, BOOST_FOREACH is a well-known library and yet the only thing they could do was to told the user that it's arguments should not contain commas, unless they could be wrapped in parenthesis, which is not always the case
Even if the replacement occurred, your code would fail in C++03, because it would create a >> symbol at the end of the template specialization, which would not be parsed correctly.
There are preprocessing / template metaprogramming tricks, however the simpler solution is to use a type without commas:
typedef std::vector<int, std::allocator<int> > FooVector;
specialize_AClass(FooVector)
Finally, there is an aesthetic issue, because of their pervasiveness, macros are best given names that cannot possibly clash with "regular" (types, functions, variables) names. The consensus is usually to use all upper case identifiers, like in:
SPECIALIZE_ACLASS
Note that this cannot begin by an underscore, because the standard restricts the use of identifiers matching _[A-Z].* or [^_]*__.* to the compiler writers for the standard library or whatever they feel like (those are not smileys :p)
Since the preprocessor runs before semantic analysis, the comma in your template parameter is being interpreted as the argument separator for the macro. Instead, you should be able to use variadic macros to do something like this:
#define specialize_AClass(...)\
template<> struct AClass< __VA_ARGS__ > { X a; };
If you are willing to add a little more code before calling your macro, you could always do this as a workaround:
typedef std::vector<int,std::allocator<int> > myTypeDef;
specialize_AClass(myTypeDef) //works
#define EMPTY()
#define DEFER( ... ) __VA_ARGS__ EMPTY()
specialize_AClass( DEFER (std::vector<int,std::allocator<int> >) )
For simple things you can use typedef
#include <vector>
template<typename A>
struct AClass {};
#define specialize_AClass(X)\
template<> struct AClass<X> { X a; };
specialize_AClass(int) //ok
typedef std::vector<int,std::allocator<int>> AllocsVector;
specialize_AClass(AllocsVector) //ok
int main()
{
return 0;
}
There are lots of other problems with your code, but to address the specific question, the preprocessor just treats < and > as less-than and greater-than operators.
That's the extent of its knowledge about C++.
There are some tricks that can be used to allow template expressions to be passed as macro arguments, but the simple and by an extremely large margin best answer for a beginner is:
DON'T DO THAT.
Cheers & hth.,
Related
I have some C++11 code using the auto inferred type that I have to convert to C++98. How would I go about converting the code, substituting in the actual type for all instances of auto?
It is going to be a PITA, but you can declare an incomplete struct template accepting a single type parameter.
Given the variable x you want to know the type of, you can use the struct with decltype(x) and that will lead to a compiler error that will show you the inferred type.
For example:
template<class Type> struct S;
int main() {
auto x = ...;
S<decltype(x)>();
}
Live demo
which will produce an error message in the form:
error: implicit instantiation of undefined template 'S<X>' (clang++)
error: invalid use of incomplete type 'struct S<X>' (g++)
with X being the inferred type. In this particular case the type is int.
Trivia: This has been recommended by Scott Meyer in one of the recent NDC 2014's videos (I don't remember which one).
As auto is known at compile-time, you need to interoperate with the compiler.
One option would be the Clang compiler's LibTooling library that provides infrastructure that you can base static analysis tools on.
For example, look at their refactoring example code that removes superfluous .c_str() calls from the code. I think you could write a similar tool that converts auto into the inferred type.
You can try to use the BOOST_AUTO macro in the Boost typeof library.
auto x = 5 + 7;
becomes
BOOST_AUTO(x,5+7);
You could use typeid and std::type_info::name();
#include <iostream>
#include <typeinfo>
#include <complex>
int
main()
{
using namespace std::literals::complex_literals;
auto x = 3.1415F;
std::cout << typeid(x).name() << '\n';
auto z = 1.0 + 1.0i;
std::cout << typeid(z).name() << '\n';
}
$ /home/ed/bin_concepts/bin/g++ -std=c++14 typeid.cpp
$ ./a.out
f
St7complexIdE
The names aren't beautiful but you can at least translate them.
These names are got from g++. The name is compiler dependent.
There is some movement to standardize a pretty_name().
Here is a non-standard way to unmangle the names.
An alternative approach would be to use function templates and type deduction. It may not work in all examples you have but it may help in some cases:
int foo ()
{
auto x = bar();
// do something with 'x'
}
Change this to:
template <typename T> int foo_(T x)
{
// do something with 'x'
}
int foo ()
{
foo_(bar());
}
auto is specified in terms of type deduction, so the above should have very similar, if not identical semantics as the C++ '11 version.
I'm trying to typedef a group of nested structs using this:
struct _A
{
struct _Sim
{
struct _In
{
STDSTRING UserName;
VARIANT Expression;
int Period;
bool AutoRun;
//bool bAutoSave;
} In;
struct _Out
{
int Return;
} Out;
} Sim;
} A;
typedef _A._Sim._In SIM_IN;
The thing is the editor in VS2010 likes it. It recognizes the elements in the typedef, I can include it as parameters to functions but when you go to build it I get warnings first C4091 (ignored on left when no variable is declared) and then that leads to error C2143 "missing ';' before '.'.
The idea of the typedef is to make managing type definitions (in pointers, prototypes, etc) to _A._Sim._In easy with one name...a seemingly perfect use for typedef if the compiler allowed it.
How can I refer to the nested structure with one name to make pointer management and type specifiction easier than using the entire nested name (_A._Sim._In) ?
The dot operator is a postfix operator applied to an object (in terms of C). I.e., you can not apply it to a type.
To reach what you want you can use a function or a macro, e.g.:
#define SIM_IN(x) x._Sim._In
It might not be preferable to do so but, if it cannot be achieved using a typedef, I guess you could always do
#define _A._Sim._In SIM_IN
But as I said you might not prefer that for various reasons. :)
I would like to perform a compile-time check on datatype sizes in a C/C++ project, and error on unexpected mismatches. Simple
#if sizeof foo_t != sizeof bar_t
does not compile - claims that sizeof is not a proper compile-time constant.
The desired scope of platforms - at the very least Visual C++ with Win32/64, and GCC on x86/amd64.
EDIT: compile-time, not necessarily preprocessor. Just not a run-time error.
EDIT2: the code assumes that wchar_t is 2 bytes. I want a compilation error if it's accidentally compiled with 4-byte wchar's.
in C++11 you can use static assert
static_assert(sizeof(foo_t) == sizeof(bar_t), "sizes do not match");
If it is pre C++11 then you can use boost static assert macro
http://www.boost.org/doc/libs/1_48_0/doc/html/boost_staticassert.html
BOOST_STATIC_ASSERT(sizeof(int)==sizeof(unsigned));
BOOST_STATIC_ASSERT_MSG(sizeof(int)==sizeof(unsigned), "sizes do not match");
You have two options:
a) static_assert of C++11
b) BOOST_STATIC_ASSERT of boost
I would prefer the first one.
Edit:
The preprocessor is not really part of the language, as the name says it pre-processes a file, it has no knowledge of the language, so it does not know sizeof.
You could use some template to do some compile time code generation, for example:
template <typename T, bool x = sizeof(T) == 4>
class X;
template <typename T>
class X<T, true> {
T v;
const char* msg() const {
return "My size is 4";
}
}
template <typename T>
class X<T, false> {
T v;
const char* msg() const {
return "My size is NOT 4";
}
}
X<int> a;
X<short> b;
If you can't use C++11 or Boost, then you might find this useful:
template <typename A, typename B>
struct MustBeSameSize {
int c[sizeof(A)-sizeof(B)];
int d[sizeof(B)-sizeof(A)];
};
template struct MustBeSameSize<int, int>;
That will only compile if and only if the sizeof the two types is identical. If they are different like this:
template struct MustBeSameSize<char, int>;
then you'll get a compile-type error, but it won't be a very readable error; maybe something like (g++ 4.4.3):
error: overflow in array dimension
This works because any modern compiler should allow zero-length arrays, but not negative-length arrays.
This works for me, and I think G++ has allowed zero-length arrays for some time. But I'm not sure how portable this is. C99 allows flexible array members (i.e. unspecified size), but I don't think that's directly relevant. In short, if you need something portable, use C++11 or use Boost.
You could define a compile time assert macro like this:
#define COMPILE_TIME_ASSERT( x ) \
switch ( x ) \
{ \
case false: \
break; \
case ( x ): \
break; \
}
If the expression is false, you will get a duplicate case label error.
I'm wondering what the difference is between using a static const and an enum hack when using template metaprogramming techniques.
EX: (Fibonacci via TMP)
template< int n > struct TMPFib {
static const int val =
TMPFib< n-1 >::val + TMPFib< n-2 >::val;
};
template<> struct TMPFib< 1 > {
static const int val = 1;
};
template<> struct TMPFib< 0 > {
static const int val = 0;
};
vs.
template< int n > struct TMPFib {
enum {
val = TMPFib< n-1 >::val + TMPFib< n-2 >::val
};
};
template<> struct TMPFib< 1 > {
enum { val = 1 };
};
template<> struct TMPFib< 0 > {
enum { val = 0 };
};
Why use one over the other? I've read that the enum hack was used before static const was supported inside classes, but why use it now?
Enums aren't lvals, static member values are and if passed by reference the template will be instanciated:
void f(const int&);
f(TMPFib<1>::value);
If you want to do pure compile time calculations etc. this is an undesired side-effect.
The main historic difference is that enums also work for compilers where in-class-initialization of member values is not supported, this should be fixed in most compilers now.
There may also be differences in compilation speed between enum and static consts.
There are some details in the boost coding guidelines and an older thread in the boost archives regarding the subject.
For some the former one may seem less of a hack, and more natural. Also it has memory allocated for itself if you use the class, so you can for example take the address of val.
The latter is better supported by some older compilers.
On the flip side to #Georg's answer, when a structure that contains a static const variable is defined in a specialized template, it needs to be declared in source so the linker can find it and actually give it an address to be referenced by. This may unnecessarily(depending on desired effects) cause inelegant code, especially if you're trying to create a header only library. You could solve it by converting the values to functions that return the value, which could open up the templates to run-time info as well.
"enum hack" is a more constrained and close-enough to #define and that helps to initialise the enum once and it's not legal to take the address of an enum anywhere in the program and it's typically not legal to take the address of a #define, either. If you don't want to let people get a pointer or reference to one of your integral constants, an enum is a good way to enforce that constraint. To see how to implies to TMP is that during recursion, each instance will have its own copy of the enum { val = 1 } during recursion and each of those val will have proper place in it's loop. As #Kornel Kisielewicz mentioned "enum hack" also supported by older compilers those forbid the in-class specification of initial values to those static const.
This is just something that has bothered me for the last couple of days, I don't think it's possible to solve but I've seen template magic before.
Here goes:
To get the number of elements in a standard C++ array I could use either a macro (1), or a typesafe inline function (2):
(1)
#define sizeof_array(ARRAY) (sizeof(ARRAY)/sizeof(ARRAY[0]))
(2)
template <typename T>
size_t sizeof_array(const T& ARRAY){
return (sizeof(ARRAY)/sizeof(ARRAY[0]));
}
As you can see, the first one has the problem of being a macro (for the moment I consider that a problem) and the other one has the problem of not being able to get the size of an array at compile time; ie I can't write:
enum ENUM{N=sizeof_array(ARRAY)};
or
BOOST_STATIC_ASSERT(sizeof_array(ARRAY)==10);// Assuming the size 10..
Does anyone know if this can be solved?
Update:
This question was created before constexpr was introduced. Nowadays you can simply use:
template <typename T>
constexpr auto sizeof_array(const T& iarray) {
return (sizeof(iarray) / sizeof(iarray[0]));
}
Try the following from here:
template <typename T, size_t N>
char ( &_ArraySizeHelper( T (&array)[N] ))[N];
#define mycountof( array ) (sizeof( _ArraySizeHelper( array ) ))
int testarray[10];
enum { testsize = mycountof(testarray) };
void test() {
printf("The array count is: %d\n", testsize);
}
It should print out: "The array count is: 10"
In C++1x constexpr will get you that:
template <typename T, size_t N>
constexpr size_t countof(T(&)[N])
{
return N;
}
The best I can think of is this:
template <class T, std::size_t N>
char (&sizeof_array(T (&a)[N]))[N];
// As litb noted in comments, you need this overload to handle array rvalues
// correctly (e.g. when array is a member of a struct returned from function),
// since they won't bind to non-const reference in the overload above.
template <class T, std::size_t N>
char (&sizeof_array(const T (&a)[N]))[N];
which has to be used with another sizeof:
int main()
{
int a[10];
int n = sizeof(sizeof_array(a));
std::cout << n << std::endl;
}
[EDIT]
Come to think of it, I believe this is provably impossible to do in a single "function-like call" in C++03, apart from macros, and here's why.
On one hand, you will clearly need template parameter deduction to obtain size of array (either directly, or via sizeof as you do). However, template parameter deduction is only applicable to functions, and not to classes; i.e. you can have a template parameter R of type reference-to-array-of-N, where N is another template parameter, but you'll have to provide both R and N at the point of the call; if you want to deduce N from R, only a function call can do that.
On the other hand, the only way any expression involving a function call can be constant is when it's inside sizeof. Anything else (e.g. accessing a static or enum member on return value of function) still requires the function call to occur, which obviously means this won't be a constant expression.
It's not exactly what you're looking for, but it's close - a snippet from winnt.h which includes some explanation of what the #$%^ it's doing:
//
// RtlpNumberOf is a function that takes a reference to an array of N Ts.
//
// typedef T array_of_T[N];
// typedef array_of_T &reference_to_array_of_T;
//
// RtlpNumberOf returns a pointer to an array of N chars.
// We could return a reference instead of a pointer but older compilers do not accept that.
//
// typedef char array_of_char[N];
// typedef array_of_char *pointer_to_array_of_char;
//
// sizeof(array_of_char) == N
// sizeof(*pointer_to_array_of_char) == N
//
// pointer_to_array_of_char RtlpNumberOf(reference_to_array_of_T);
//
// We never even call RtlpNumberOf, we just take the size of dereferencing its return type.
// We do not even implement RtlpNumberOf, we just decare it.
//
// Attempts to pass pointers instead of arrays to this macro result in compile time errors.
// That is the point.
//
extern "C++" // templates cannot be declared to have 'C' linkage
template <typename T, size_t N>
char (*RtlpNumberOf( UNALIGNED T (&)[N] ))[N];
#define RTL_NUMBER_OF_V2(A) (sizeof(*RtlpNumberOf(A)))
The RTL_NUMBER_OF_V2() macro ends up being used in the more readable ARRAYSIZE() macro.
Matthew Wilson's "Imperfect C++" book also has a discussion of the techniques that are used here.
The Problem
I like Adisak's answer:
template <typename T, size_t N>
char ( &_ArraySizeHelper( T (&arr)[N] ))[N];
#define COUNTOF( arr ) (sizeof( _ArraySizeHelper( arr ) ))
It's what Microsoft uses for the _countof macro in VS2008, and it's got some nice features:
It operates at compile time
It's typesafe (i.e. it will generate a compile-time error if you give it a pointer, which arrays degrade too all too easily)
But as pointed out by Georg, this approach uses templates, so it's not guaranteed to work with local types for C++03:
void i_am_a_banana() {
struct { int i; } arr[10];
std::cout << COUNTOF(arr) << std::endl; // forbidden in C++03
}
Fortunately, we're not out luck.
The Solution
Ivan Johnson came up with a clever approach that wins on all accounts: it's typesafe, compile-time, and works with local types:
#define COUNTOF(arr) ( \
0 * sizeof(reinterpret_cast<const ::Bad_arg_to_COUNTOF*>(arr)) + \
0 * sizeof(::Bad_arg_to_COUNTOF::check_type((arr), &(arr))) + \
sizeof(arr) / sizeof((arr)[0]) )
struct Bad_arg_to_COUNTOF {
class Is_pointer; // incomplete
class Is_array {};
template <typename T>
static Is_pointer check_type(const T*, const T* const*);
static Is_array check_type(const void*, const void*);
};
For those who are interested, it works by inserting two "tests" before the standard sizeof-based array-size macro. Those tests don't impact the final calculation, but are designed to generate compile errors for non-array types:
The first test fails unless arr is integral, enum, pointer, or array. reinterpret_cast<const T*> should fail for any other types.
The second test fails for integral, enum, or pointer types.
Integral and enum types will fail because there's no version of check_type that they match, since check_type expects pointers.
Pointer types will fail because they'll match the templated version of check_type, but the return type (Is_pointer) for the templated check_type is incomplete, which will produce an error.
Array types will pass because taking the address of an array of type T
will give you T (*)[], aka a pointer-to-an-array, not a pointer-to-a-pointer. That means that the templated version of check_type won't match. Thanks to SFINAE, the compiler will move on to the non-templated version of check_type, which should accept any pair of pointers. Since the return type for the non-templated version is defined completely, no error will be produced. And since we're not dealing with templates now, local types work fine.
If you are on a Microsoft only platform, you can take advantage of the _countof macro. This is a non-standard extension which will return the count of elements within an array. It's advantage over most countof style macros is that it will cause a compilation error if it's used on a non-array type.
The following works just fine (VS 2008 RTM)
static int ARRAY[5];
enum ENUM{N=_countof(ARRAY)};
But once again, it's MS specific so this may not work for you.
You can't solve it in general, thats one the reasons for array wrappers like boost array (plus stl-style behaviour of course).
It appears not to be possible to obtain the sizeof array as a compile-time constant without a macro with current C++ standard (you need a function to deduce the array size, but function calls are not allowed where you need a compile-time constant). [Edit: But see Minaev's brilliant solution!]
However, your template version isn't typesafe either and suffers from the same problem as the macro: it also accepts pointers and notably arrays decayed to a pointer. When it accepts a pointer, the result of sizeof(T*) / sizeof(T) cannot be meaningful.
Better:
template <typename T, size_t N>
size_t sizeof_array(T (&)[N]){
return N;
}
Without C++0x, the closest I can get is:
#include <iostream>
template <typename T>
struct count_of_type
{
};
template <typename T, unsigned N>
struct count_of_type<T[N]>
{
enum { value = N };
};
template <typename T, unsigned N>
unsigned count_of ( const T (&) [N] )
{
return N;
};
int main ()
{
std::cout << count_of_type<int[20]>::value << std::endl;
std::cout << count_of_type<char[42]>::value << std::endl;
// std::cout << count_of_type<char*>::value << std::endl; // compile error
int foo[1234];
std::cout << count_of(foo) << std::endl;
const char* bar = "wibble";
// std::cout << count_of( bar ) << std::endl; // compile error
enum E1 { N = count_of_type<int[1234]>::value } ;
return 0;
}
which either gives you a function you can pass the variable to, or a template you can pass the type too. You can't use the function for a compile time constant, but most cases you know the type, even if only as template parameter.
Now STL libraries are available to decide/select array size compile time
#include <iostream>
#include <array>
template<class T>
void test(T t)
{
int a[std::tuple_size<T>::value]; // can be used at compile time
std::cout << std::tuple_size<T>::value << '\n';
}
int main()
{
std::array<float, 3> arr;
test(arr);
}
Output:
3