Related
I wrote a template function, that should take a reference to array of const elements, that has certain size. But for some reason the compiler says that this function doesn't match, when I call it
#include<iostream>
struct Node
{
int key, left, right;
};
template <int N>
bool isCorrect(const Node (&nodes)[N])
{
// doesn't matter
return true;
}
int main ()
{
int n;
std::cin >> n;
Node nodes[n];
std::cout << (isCorrect(nodes) ? "CORRECT" : "iNCORRECT") << '\n';
return 0;
}
It gave me a rather mysterious error message that I couldn't decipher:
"candidate template ignored couldn't match **Node** against **Node"**.
I pretty sure that template can be used to determine array size, like I'm trying to do, but this fails.
Is this due to the fact that I use a non-primitive type?
Yes, I know I can use vector and avoid this problem altogether.
But I really want to know what the hell is going on when compiler can't match a type against itself.
What I can do to avoid this strange message in future?
When you write this:
int n;
std::cin >> n;
You are assigning a value to n at runtime.
However, template arguments must be known at compile-time. This is because the compiler needs them in order to generate the function (that it will then compile and export to your library).
The syntax:
Node nodes[n];
is called a Variable Length Array, and it's a compiler extension. It's not portable C++. The compiler makes it look like a regular array, but it's not.
To fix your problem, n must be known at compile time:
constexpr int n = 1;
Node nodes[n];
std::cout << (isCorrect(nodes) ? "CORRECT" : "iNCORRECT") << '\n';
Live Demo
Disclaimer: This question is a bit complicated because it's several questions in one, but they're all related to the same sort of concept/issue.
Premise:
consexpr functions may only consist of a single return statement.
They can call other functions and use conditionals, but theoretically they should demonstrate functional purity, and thus the results should be cachable (by the compiler, at compile time) in some sort of map so that the compiler doesn't have to constantly re-evaluate the same function.
Question(s):
Is this assumption correct or is there something I haven't considered that makes it impossible to cache the result of a constexpr function?
If no, does this mean that constexpr functions have to be calculated every time they're used?
What about templates? Are constexpr values on templates cachable or do they also have to be recalculated each time?
I don't believe constexpr functions are required to be pure - at least, not for all possible arguments. Consider:
#include <iostream>
#include <stdlib.h>
constexpr int f(int n) { return n == 0 ? 42 : rand(); }
template <int n> void g() {}
int main()
{
g<f(0)>(); // OK
// g<f(1)>(); // error
std::cout << f(0) << ' ' << f(1) << ' ' << f(2);
}
Output: 42 1804289383 846930886. Demo
I wondered if I could auto deduce the size of an array, which is passed as a template parameter, without (explicitly) passing its size.
The following code both compiles warning-less on g++ 4.8 and clang++ 3.3 (using -std=c++11 -Wall).
#include <iostream>
template<const int* arr>
struct array_container
{
static constexpr int val = arr[1];
array_container() {
std::cout << val << std::endl;
}
// static constexpr int arr_size = ??;
};
constexpr int one[] = { 1 };
constexpr int two[] = { 1, 2 };
int main()
{
// array_container<one> array_one;
array_container<two> array_two;
// (void) array_one;
(void) array_two;
return 0;
}
However, if I remove the two comment signs in main(), I get an out of bound error with both compilers.
Now, this is cool. Somehow the compiler knows the size of the array, though the type of const int* arr is a pointer. Is there any way to get the size of arr, e.g. to complete my comment in array_container?
Of course, you are not allowed to
Use any macros
Store the size in arr (e.g. passing an std::array as template parameter: constexpr std::array<int, 1> one = { 1 }, or using an end marker like '\0' in strings)
Use an additional template parameter for the size that can not be auto deduced (array_container<1, one> array_one).
Maybe std::extent template from <type_traits> header of C++11 standard library is what you want:
#include <iostream>
#include <type_traits>
constexpr int one[] = { 1 };
constexpr int two[] = { 1, 2 };
int main()
{
std::cout << std::extent<decltype(one)>::value << std::endl;
std::cout << std::extent<decltype(two)>::value << std::endl;
return 0;
}
Output:
1
2
template<size_t size>
constexpr size_t arraySize ( const int ( &arrayRef ) [size] ) {
return size;
}
int main(){
int A[1];
int B[2];
cout << arraySize(A) << arraySize(B);
return 0;
}
I believe something like this is what you're looking for, using array references. The syntax for declaring an array reference looks kind of like the syntax for a function pointer. This function template accepts an array reference named arrayRef, which prevents array-to-pointer decay so that compile-time info about array size is preserved. As you can see, the template argument is implicit to the compiler. Note that this can only work when the size can be deduced at compile time. Interestingly, this should still work without naming arrayRef at all. To make the above template more useful, you can add a template parameter to deduce the type of the array as well. I left it out for clarity.
Probably not, as SFINAE only happens in the immediate context, while that error comes from the requirement that UB in constexpr lead to a compile time error, which I think is not immediate. You could try a recursive SFINAE that stops on the UB, but even if it worked you would have to both check the standard and hope it does not change (as it is rather obscure and new).
The easy way is to ise s function to deduce the array size, have to explicitly pass it to the type, then store it in an auto. Probably not what you want.
There are proposals to allow type parameters to be deduced from value parameters, so you could wait for those instead.
Not a solid answer, more of an extended comment, so marked community wiki.
It is indeed possible. I found a solution using SFINAE. What it basically does is produce a substitution error if the index is out of bound (line 3 in this example):
template<class C>
static yes& sfinae(typename val_to_type<
decltype(*C::cont::data), *(C::cont::data + C::pos)>::type );
template<class C>
static no& sfinae(C );
The full source code is on github.
There are only two disadvantages:
You have to specify the type of the array (this can not be avoided)
It only works with g++ 4.8.1 and clang 3.3. g++ fails for empty strings (with a compiler bug). If someone can test for other compilers, that would be appreciated.
I'm writing C++ using the MinGW GNU compiler and the problem occurs when I try to use an externally defined integer variable as a case in a switch statement. I get the following compiler error: "case label does not reduce to an integer constant".
Because I've defined the integer variable as extern I believe that it should compile, does anyone know what the problem may be?
Below is an example:
test.cpp
#include <iostream>
#include "x_def.h"
int main()
{
std::cout << "Main Entered" << std::endl;
switch(0)
{
case test_int:
std::cout << "Case X" << std::endl;
break;
default:
std::cout << "Case Default" << std::endl;
break;
}
return 0;
}
x_def.h
extern const int test_int;
x_def.cpp
const int test_int = 0;
This code will compile correctly on Visual C++ 2008. Furthermore a Montanan friend of mine checked the ISO C++ standard and it appears that any const-integer expression should work. Is this possibly a compiler bug or have I missed something obvious?
Here's my compiler version information:
Reading specs from C:/MinGW/bin/../lib/gcc/mingw32/3.4.5/specs
Configured with: ../gcc-3.4.5-20060117-3/configure --with-gcc --with-gnu-ld --with-gnu-as --host=mingw32 --target=mingw32 --prefix=/mingw --enable-threads --disable-nls --enable-languages=c,c++,f77,ada,objc,java --disable-win32-registry --disable-shared --enable-sjlj-exceptions --enable-libgcj --disable-java-awt --without-x --enable-java-gc=boehm --disable-libgcj-debug --enable-interpreter --enable-hash-synchronization --enable-libstdcxx-debug
Thread model: win32
gcc version 3.4.5 (mingw-vista special r3)
A case label requires an integral constant expression which have strict requirements that enable their value to be determined at compile time at the point of use.
From 5.19 [expr.const], "an integral constant expression can involve only literals (2.13), enumerators, const variables or static data members of integral or enumeration types initialized with constant expressions (8.5),...".
At the point at which you use test_int where a constant expression is required, it is a const variable declared extern and without any initializer and does not meet the requirements for a constant expression, despite the fact that you do actually initialize it with a integral constant expression in another translation unit. (*This is not completely clear from the wording of the standard but is my current interpretation of it.)
The restrictions in the standard disallow usages such as:
void f(int a, int b)
{
const int c = b;
switch (a)
{
case c:
//...
}
}
In your example, when the compiler is compiling test.cpp, it has no way to determine what the initializer might be in x_def.cpp. You might have done:
const int test_int = (int)time();
Clearly, in neither of these examples could the value of the const int be determined at compile time which is the intention for integral constant expressions.
Case labels have to be compile-time constants. That means the compiler must be able to substitute the value at compile-time. Although your values are constant, the compiler can't know their values until at least link-time.
VC++ is right, and g++ is wrong. A case label is required to be an integral constant expression (§6.4.2/2) and a const variable of integer type initialized with a constant expression is a constant expression (§5.19/1).
Edit:mostly for Pavel, and his suggestion of a possible DR. §5.19/2 has been completely rewritten already. C++0x adds a whole new concept of a constexpr that expands what's considered a constant expression considerably. For example, under the current standard, something like:
int x() { return 10; }
const int y = x();
y is not a constant expression. We can all easily see that it's (indirectly) initialized with a literal 10, but the compiler still can't allow it as a constant expression. Under the new standard, it'll be possible designate x() as a constexpr, and y will be a constant expression.
As it's formulated in N2960, §5.19/2 says an expression is a constant expression unless it uses something from the following list. It then gives about a page-long list, but using a const variable that isn't initialized in the current compilation unit doesn't seem to be one of them. [Edit: see below -- reading CWG Issue 721, I've changed my mind.]
As far as VC++ being right and g++ wrong, I meant only in this very specific respect. There's no question that both are "wrong" if you're talking about getting every part of the standard correct. I doubt anybody's even working on implementing export for either one.
export does, however, point out a degree to which C++ seems willing to postpone decisions until link time. Two-phase name lookup means that when an exported template is compiled, there's a lot more than just constant expressions that it doesn't know for sure. It might not even know whether a particular name refers to a function or an object -- but there's no question that the standard does require exactly that. The issue at hand strikes me as a substantially simpler one to deal with.
Edit: I did a bit of searching, and found Core Working Group Issue 721. Jame's question parallels the one at hand quite closely ("However, this does not require, as it presumably should, that the initialization occur in the same translation unit and precede the constant expression..."). The proposed resolution adds the phrase: "...with a preceding initialization...". At least as I read it, that means that the committee agreed that under the current standard, the code must be accepted, but under the new standard it's not allowed.
That wording was agreed upon in July of this year, but doesn't (yet?) appear in N2960, which I believe is the most recent draft of C++0x.
I cannot reproduce this on a trivial example using VC++2008:
test.cpp:
extern const int n;
int main() {
switch (0) {
case n: break;
}
}
test2.cpp:
extern const int n = 123;
compile with:
cl.exe test.cpp test2.cpp
output:
test.cpp(4) : error C2051: case expression not constant
MS compiler is being a bit naughty here. When you compile the the constant initialization and the case statement using the constant in the same compilation unit it works out the constant value at compile time.
Once you attempt to use the extern const outside of the compilation unit where it's initialised (i.e. the cpp file containing initialization or any of the files it includes) the compiler will barf with pretty much the same error. Fred Larson is correct the compiler shouldn't know the constant value until link time and thus it must not be acceptable as a switch constant, it's just MS compiler cheats a little bit.
The solution to your problem would be to use macros, is there any reason why you don't want to #define the constant?
Here's a simpler test:
test_int.cpp:
const int test_int = 10;
main.cpp:
#include <iostream>
using std::cout;
using std::endl;
extern const int test_int;
int main() {
cout << test_int << endl;
return 0;
}
In G++, I get an undefined reference. However, doing the same thing in C works. According to http://gcc.gnu.org/ml/gcc/2005-06/msg00325.html , a const variable implicitly has internal linkage in C++. This doesn't appear to be the case in C.
I'm using a "gcc (SUSE Linux) 4.3.2" and having a similar effect, that still is a bit stranger.
My definitions are:
namespace operations{
const cOpDummy OpDummy();
const cInitOperator InitOperator();
};
const unsigned long ulNumberOfOperations = 2;
const cOperation * arrayOperations[] = {
& (operations::OpDummy),
& (operations::InitOperator)
};
And the extern declarations in an other file are:
extern const unsigned long ulNumberOfOperations;
extern const cOperation * arrayOperations[];
The funny thing is: The compiler gives just for "ulNumberOfOperations" "undefined reference to ulNumberOfOperations", but is Ok with "arrayOperations[]".
My workaround is to declare "ulNumberOfOperations" not constant.
Since c++11 you could build a little template framework to give you a syntax like this:
void test(int a, int x, int y, int z)
{
std::cout << "given " << a << ", choosing ";
given(a)
.when(x, [] { std::cout << "x\n"; })
.when(y, [] { std::cout << "y\n"; })
.when(z, [] { std::cout << "z\n"; })
.when(any_other, [] { std::cout << "none of the above\n"; });
}
Full demo:
#include <iostream>
struct any_object {};
constexpr auto any_other = any_object {};
template<class Expr>
struct when_object
{
template<class T, class F>
constexpr when_object& when(T const& value, F&& f)
{
if (not executed and expr == value) {
executed = true;
f();
}
return *this;
}
template<class F>
constexpr void when(any_object, F&& f)
{
if (not executed) {
executed = true;
f();
}
}
Expr const& expr;
bool executed = false;
};
template<class Expr>
constexpr auto given(Expr const& expr)
{
return when_object<Expr> {expr};
}
void test(int a, int x, int y, int z)
{
std::cout << "given " << a << ", choosing ";
given(a)
.when(x, [] { std::cout << "x\n"; })
.when(y, [] { std::cout << "y\n"; })
.when(z, [] { std::cout << "z\n"; })
.when(any_other, [] { std::cout << "none of the above\n"; });
}
int main()
{
test(4, 4, 5, 6);
test(4, 3, 4, 5);
test(4, 2, 3, 4);
test(1, 2, 3, 4);
}
expected results:
given 4, choosing x
given 4, choosing y
given 4, choosing z
given 1, choosing none of the above
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