I am working with a variable of type itk::Image<OutputPixelType, Dimension>, where "itk" comes from the image processing library ITK.
The following code compiles:
constexpr unsigned int Dimension = 3;
using PixelType = float;
using MyImageType = itk::Image<PixelType, Dimension>;
But now I need to define "Dimension" as something computed from a function.
unsigned int Dimension = get_dimension(...);
My compiler gives an error:
error: non-type template argument is not a constant expression
using MyImageType = itk::Image<PixelType, Dimension>;
^~~~~~~~~
How could I work around this issue? I hope to use "Dimension" as something computed from a function.
Your get_dimension function should be constexpr and, if that is the case, you can have the following:
constexpr unsigned int Dimension = get_dimension(...);
Example
Let's say you have the following simplified class:
template <int v>
class Foo {
public:
constexpr Foo()
: v_(v)
{}
private:
int v_;
};
and then the following:
int v = get();
using FooInt = Foo<v>;
where get function is defined as follows:
int get() {
return 1;
}
You will get the same as error as you are getting in your example.
Therefore, the solution would be to mark get function constexpr and make the v value also constexpr like:
constexpr int get() {
return 1;
}
constexpr int v = get();
using FooInt = Foo<v>;
Take a look at the demo
UPDATE
In order to be able to use templates, compiler needs to know template parameters at compile time, and therefore, if Dimension is not a constexpr (which declares that it is possible to evaluate the value of the variable at compile time) variable, it cannot be used as template parameter.
Related
For the purposes of metaprogramming, I would like to store a member function pointer in a type, and later use it to parameterise a template.
By analogy, here is a working example of how I can store an int in an integer_constant type:
template< int I >
struct integer_constant {
static constexpr int value = I;
};
template <int I>
struct A {
// (client type, probably does other things with I)
static constexpr int value = I;
};
namespace {
using cStored= integer_constant<42>; // store value
static_assert(cStored::value == 42, "");
// ...
using aUseStored = A<cStored::value>; // use value as template parameter
static_assert(aUseStored::value == 42, "");
}
Can I do the same thing with member function pointers? If not, why not?
struct S{
void foo() {}
};
typedef void (S::*s_member_fn_type)();
template< s_member_fn_type M >
struct member_fn_constant {
static constexpr s_member_fn_type value = M;
};
template <s_member_fn_type M>
struct A {
// (client type, probably does other things with M)
static constexpr s_member_fn_type value = M;
};
namespace {
using cStored = member_fn_constant<&S::foo>; // store value
// clang is ok with the following line
// gcc 6.2: error: non-constant condition for static assertion
// gcc 6.2: error: '(s_member_fn_type)member_fn_constant<&S::foo>::value' is not a constant expression
static_assert(cStored::value == &S::foo, "");
// following line gives:
// clang 3.9.0 error: non-type template argument is not a pointer to member constant
// gcc 6.2: error: could not convert template argument 'member_fn_constant<&S::foo>::value' to 'void (S::*)()'
using aUseStored = A<cStored::value>; // use value as template parameter
//static_assert(aUseStored ::value == &S::foo, "");
}
I understand that I can add an extra level of indirection by passing the wrapper struct, instead of the function pointer, as follows:
template <typename MT>
struct B {
static constexpr s_member_fn_type value = MT::value;
};
namespace {
using bUseStored = B<cStored>;
}
But this does not help if my client class A is already defined to take a member function pointer.
Pre-C++17, pointer to member function is not a constant expression.
From C++17, It's a constant expression as addressed by N4268.
clang has supported it with -std=c++1z from clang 3.5 as you can see C++ Support in Clang
g++ has claimed that it had supported it from g++ 6 but it seems not true, see C++ Standards Support in GCC
This is a continuation of the problem I found and described here.
Say you have a struct that contains a static constexpr function and a type alias for a std::bitset (or any type you wish to template using the result of the const expression) that looks as follows:
struct ExampleStruct {
static constexpr std::size_t Count() noexcept {
return 3U;
}
using Bitset = std::bitset<Count()>;
};
Visual Studio 2015 version 14.0.25029.00 Update 2 RC highlights the Count() call in red and generates the error function call must have a constant value in a constant expression.
How might one get this to compile, or achieve similar results?
What exactly is causing the error here? Is the compiler trying to generate the type alias before the const expression function?
EDIT: The explanation for why this does not work can be found below, but since no one provided possible workarounds, here are some that I came up with:
(1) When using templates, store type alias to this type.
template<typename T>
struct ExampleStruct {
using ThisType = ExampleStruct<T>;
static constexpr std::size_t Count() noexcept {
return 3U;
}
using Bitset = std::bitset<ThisType::Count()>;
};
(2) Move Count() function outside of the struct body.
static constexpr std::size_t Count() noexcept {
return 3U;
}
struct ExampleStruct {
using Bitset = std::bitset<Count()>;
};
(3) Replace constexpr method with constexpr member variable.
struct ExampleStruct {
static constexpr std::size_t Count = 3U;
using Bitset = std::bitset<Count>;
};
(4) Store value in constexpr member variable, and return this from Count() method.
struct ExampleStruct {
private:
static constexpr std::size_t m_count = 3U;
public:
static constexpr std::size_t Count() noexcept {
return m_count;
}
using Bitset = std::bitset<m_count>;
};
You might have noticed that if you move one or both lines outside of the class body, the error goes away. The problem you're running into is that class member function definitions (even inline ones) are not parsed until after the entire class definition has been parsed; therefore, when the compiler sees using Bitset = std::bitset<Count()>;, at that point Count has been declared but not yet defined, and a constexpr function that has not been defined cannot be used in a constant expression -- so you get the error you're seeing. Unfortunately, I know of no good solution or workaround for this.
#include <algorithm>
struct S
{
static constexpr int X = 10;
};
int main()
{
return std::min(S::X, 0);
};
If std::min expects a const int&, the compiler very likely would like to have the S::X also defined somewhere, i.e. the storage of S::X must exists.
See here or here.
Is there a way to force the compiler to evaluate my constexpr at compile time?
The reason is:
Initially, we had a problem in early initialization of static variables in the init priority. There was some struct Type<int> { static int max; };, and some global static int x = Type<int>::max;, and some other early code other_init used that x. When we updated GCC, suddenly we had x == 0 in other_init.
We thought that we could avoid the problem by using constexpr, so that it would always evaluate it at compile time.
The only other way would be to use struct Type<int> { static constexpr int max(); }; instead, i.e. letting it be a function.
For types that are allowed to exist as template value parameters, you can introduce a data structure like this:
template <typename T, T K>
struct force
{
static constexpr T value = K;
};
Usage:
force<int, std::min(S::X, 0)>::value
The constexpr is evaluated at compile time. Your problem is
due to the fact that std::min is not a constexpr, so
regardless of its input, the results are not a const expression
(and in particular, if you initialize a variable with static
lifetime using std::min, it is dynamic initialization).
The simplest solution is probably to define your own min,
something along the lines of:
template <typename T>
constexpr T staticMin( T a, T b )
{
return a > b ? b : a;
}
This should result in full evaluation at compile time, and
static initialization.
What I want to do is:
int const bitsPerInt = log2(X);
bitset<bitsPerInt> bits(a random number...);
but I get this error:
'bitsPerInt' cannot appear in a constant expression
error: template argument 1 is invalid
If you really need this to work, make your own log2 that works in compile-time and pass it to bitset's template argument.
constexpr unsigned Log2(unsigned n, unsigned p = 0) {
return (n <= 1) ? p : Log2(n / 2, p + 1);
}
constexpr size_t bitCount = Log2(X);
std::bitset<bitCount> bits;
Live example.
Here's the solution using template meta-programming i.e. without using constexpr:
template<int N,unsigned int P=0>
struct Log2 { enum { value = Log2<N/2,P+1>::value }; };
template <unsigned p>
struct Log2<0, p> { enum { value = p }; };
template <unsigned p>
struct Log2<1, p> { enum { value = p }; };
std::bitset<Log2<4>::value> bits;
Live example.
This version should work in both C++03 and C++11; however, if you've access to C++11, I'd still recommend the constexpr way since it's cleaner (easier to understand).
Template parameter needs to be known(and constant if it is a value and not a type) at compile time. This is how templates work in C++. Templates actually generate real code for each specific version of the generic code.
Given a template whose non-type parameter determines the size of a non-const int array member, how can I access the array elements by an integral index at compile time? I want the access to be done via the class template’s getter method at.
I figured since class templates must be instantiated before runtime, I can pass another non-type class template’s enum member value to the prior class’s at method to ensure the index argument is a compile-time constant.
I left the class template deliberate_error undefined to see if its arguments are computed at compile time and to view the compile-time results in the error messages.
template <unsigned int N>
struct compile_time_int {
enum {num = N};
};
template <unsigned int N>
struct array_wrapper {
int arr[N];
template <unsigned int Ind>
constexpr int const& at(compile_time_int<Ind> const& index) const {
return arr[index.num];
}
};
template <unsigned int> struct deliberate_error;
int main() {
compile_time_int<2> cti;
array_wrapper<3> aw;
aw.at(cti);
deliberate_error<cti.num> my_error1;
deliberate_error<aw.at(cti)> my_error2;
}
aw.at(cti); doesn’t give an error, so I thought that if I passed the same expression to deliberate_error instance my_error2, the compiler will display the value of arr[2] in the error message.
my_error1 causes g++ error: aggregate 'deliberate_error<2u> my_error1' has incomplete type and cannot be defined,
showing cti’s wrapped integral value 2. So, I thought if I passed the same cti to object aw's getter, and then pass the result to my_error2, I can get arr[2] in the error message. But instead, it prints:
error: the value of 'aw' is not usable in a constant expression
note: 'aw' was not declared 'constexpr'
note: in template argument for type 'unsigned int'
error: invalid type in declaration before ';'
So, I tried prepending constexpr to aw’s declaration, but that gives even more undesirable errors. What’s wrong here, and how can I fix it?
(Note that as far as I see, std::array with std::get already solves your problem.)
The main issue is that you need your instance aw to be constexpr and of course you need to initialize it with some values:
constexpr array_wrapper<3> aw = { 1, 2, 3 };
Regarding the function at, you can write it as a normal function but simply specify it as constexpr:
constexpr int const& at(int i) const {
return arr[i];
}
Then, aw.at(0) can be used as a constant expression: Live Demo
The advantage of this is that you can use this function in both compile-time and runtime expressions, with static and dynamic indexing, respectively.
If you really want it to be templated, you can either write it as a non-member like std::get<N> or as a class member, but use a template parameter of type int (or size_t or similar). That simplifies its definition (and you can get rid of your compile_time_int class template):
template<int Index>
constexpr int const& at() const {
return arr[Index];
}
Then, aw.at<0>() can be used as a constant expression: Live Demo
The advantage of the second method is that the index is guaranteed to be static, so we can use it in the function for static bound checking, which will not add any performance penalty. I don't know if this is possible with the first version.
Maybe just this:
template <unsigned int N>
struct array_wrapper
{
int arr[N];
};
template <unsigned int I, unsigned int N>
constexpr int & at(array_wrapper<N> & a)
{
static_assert(I < N, "static array index out of bounds");
return a.arr[I];
}
// add a "const" overload, too
Usage:
array_wrapper<10> x;
at<3>(x) = 42;