I would like to reference two earlier posts:
why-is-comparing-two-parameters-of-a-constexpr-function-not-a-constant-condition
how-does-this-function-template-deduce-the-size-of-an-array
In the first discussion, it has been pointed out that the compilation error
error: non-constant condition for static assertion
is due to the fact that the constexpr function under consideration could be invoked with arguments evaluated during run-time.
In the second discussion, it has been pointed out that the template function method for getting at the size of the template array, works due to template argument type deduction by the compiler, which happens during compilation.
The following code gives me this error for static assertion:
In file included from main.cpp:1:
classA.h: In instantiation of ‘void doSomething(A<T> (&)[2]) [with T = int; array2As<T> = A<int> [2]]’:
main.cpp:6:18: required from here
classA.h:65:20: error: non-constant condition for static assertion
65 | static_assert(2 == sz, "Compilation error: array must have exactly 2 elements");
| ~~^~~~~
compilation terminated due to -Wfatal-errors
//classA.h
#include <type_traits>
#include <cstddef>
//#include <iterator>
#include <iostream>
using std::is_same;
//using std::size;
using std::size_t;
using std::cout;
using std::endl;
template<typename T> class A;
template<typename T>
using array2As = A<T>[2];
template<typename T>
void doSomething (array2As<T>&);
template<template<typename>class A, typename T, size_t N>
constexpr size_t cal_size(const A<T>(&)[N]){
return N;
}
template<typename T>
class A{
public:
A(T);
private:
friend void doSomething<>(array2As<T>&);
A()=delete;
A(const A&)=delete;
A& operator=(const A&)=delete;
T elem;
};
template<typename T>
A<T>::A(T elem){
static_assert(is_same<T,int>::value || is_same<T,double>::value, "Compilation error: type must be int or double");
this->elem = elem;
}
template<typename T> void doSomething (array2As<T>& a){
auto sz = cal_size(a);
cout << sz << endl;
static_assert(2 == sz, "Compilation error: array must have exactly 2 elements");
const auto& obj1 = a[0];
cout << obj1.elem << endl;
const auto& obj2 = a[1];
cout << obj2.elem << endl;
return;
}
//main.cpp
#include "classA.h"
int main (){
array2As<int> a = {A(5),A(7)};
doSomething<int>(a);
array2As<double> b = {A(1.2),A(6.3)};
doSomething<double>(b);
return 0;
}
The methods involved, i.e., cal_size() and doSomething() are function templates themselves, so going by the explanation in the second post, the value stored inside the variable sz as returned from cal_size() should be a compile time constant.
So why is it that I am still getting this error?
TIA
cal_size(a)is (currently) a constant expression, but you store its result into a non-const(expr)variable which can have its value changed at any point at runtime, soszisn't usable in constant expressions. Addconstexpron its declaration. And then it will likely still fail because there is a recent defect report against the standard that your compiler likely hasn't implemented yet before whichcal_size(a)was not a constant expression specifically becauseais a reference.aby-reference which is necessary for a built-in array to even have the type information. Passing astd::arrayby-value would work. If you still want to do it your way, you need to operate directly on the type ofa, notaitself. E.g. by usingstd::extentinstead of yourcal_size.