I have a problem when I want to check certain template-parameters for their validity using some helper struct and constepxr functions. As long as there is no reference to the static constexpr member I want to initialize the compiler decides not to evaluate the expression. The code I use is the following:
#include <cstddef>
#include <iostream>
#define CONSTEXPR static constexpr
using namespace std;
template<size_t ... Sizes>
struct _size_check_impl
{
static_assert(sizeof...(Sizes) != 0, "Dimension has to be at least 1");
CONSTEXPR size_t dimension = sizeof...(Sizes);
};
template<size_t ... Sizes>
constexpr size_t check_sizes()
{
return _size_check_impl<Sizes...>::dimension;
}
template<size_t ... Sizes>
struct Test
{
static constexpr size_t Final = check_sizes<Sizes...>();
};
int main()
{
Test<> a; // This shouldn't get through the static assert
Test<1, 2> b; // Passing
Test<2> c; // Passing
// cout << Test<>::Final; // With this it works just fine, bc Final is accessed
return 0;
}
Is there a way I can do this, some proxy dependecy that forces the compiler to evaluate the Final value if constexpr are evaluated? Is there another, clean way to check this property clean and quickly?
The simple answer would probably be to simply add another static_assert:
template<size_t ... Sizes>
struct Test
{
static constexpr size_t Final = check_sizes<Sizes...>();
static_assert(Final > 0, "");
};
This will lead to two separate static assertion failures, though. If that is a problem for you, you could make sure check_sizes, or Final, is used some other way that must necessarily be evaluated at template class instantiation time, without instantiation of any member, for instance:
template<size_t ... Sizes>
struct Test
{
static constexpr decltype(check_sizes<Sizes...>(), size_t()) Final = check_sizes<Sizes...>();
};
Yet another option: if Test<...> is a class that is expected to be constructed normally, you could make sure Final is used from the constructor somehow.
Related
Take a look at this piece of code:
#include <iostream>
using namespace std;
using ld = long double;
template<int i>
struct A {
static_assert(false,"");
constexpr static int value = 3;
};
template<int i>
struct B {
constexpr static int value = i*i*i;
};
template<int i>
struct CheckVal {
constexpr static int value = conditional<i == 1,A,B><3>::value;
};
This is supposed to terminate the compilation if a 1 is passed to CheckVal, but I'm getting the following error on compilation, no matter what is passed to CheckVal:
error: use of class template 'A' requires template arguments
constexpr static ld value = conditional<i == 1,A,B><3>::value;
What is the problem here? How can I fix it?
The only place, where you use A, is inside conditional<>.
A requires a template argument, namely template<int i>.
So, instead of A, you must say A<i> or A<3> or ... same for B.
And finally, you must remove <3> as your compiler will tell you:
template<int i>
struct CheckVal {
constexpr static int value = conditional<i == 1, A<i>, B<i> >::value;
};
However, the compiler (at least g++) will fail with
error: static assertion failed:
static_assert(false,"");
^
First of all your static_assert will always trigger, so not sure what was the purpose of it. If you comment it out, this is what you need to change in CheckVal to make it work:
template<int i>
struct CheckVal
{
constexpr static int value = std::conditional<i == 1, A<3>, B<3>>::type::value;
};
std::conditional will select either A<3> or B<3> depending on condition, then you first need to return the type ::type and only then you can get the ::value member
Demo: https://ideone.com/tozaYr
I'm not really sure what you are trying to achieve but isn't this much simpler construct sufficient?
template<int i>
struct CheckVal {
static_assert(i != 1,"");
};
Lets say that you have a function which generates some security token for your application, such as some hash salt, or maybe a symetric or asymetric key.
Now lets say that you have this function in your C++ as a constexpr and that you generate keys for your build based on some information (like, the build number, a timestamp, something else).
You being a diligent programmer make sure and call this in the appropriate ways to ensure it's only called at compile time, and thus the dead stripper removes the code from the final executable.
However, you can't ever be sure that someone else isn't going to call it in an unsafe way, or that maybe the compiler won't strip the function out, and then your security token algorithm will become public knowledge, making it more easy for would be attackers to guess future tokens.
Or, security aside, let's say the function takes a long time to execute and you want to make sure it never happens during runtime and causes a bad user experience for your end users.
Are there any ways to ensure that a constexpr function can never be called at runtime? Or alternately, throwing an assert or similar at runtime would be ok, but not as ideal obviously as a compile error would be.
I've heard that there is some way involving throwing an exception type that doesn't exist, so that if the constexpr function is not deadstripped out, you'll get a linker error, but have heard that this only works on some compilers.
Distantly related question: Force constexpr to be evaluated at compile time
In C++20 you can just replace constexpr by consteval to enforce a function to be always evaluated at compile time.
Example:
int rt_function(int v){ return v; }
constexpr int rt_ct_function(int v){ return v; }
consteval int ct_function(int v){ return v; }
int main(){
constexpr int ct_value = 1; // compile value
int rt_value = 2; // runtime value
int a = rt_function(ct_value);
int b = rt_ct_function(ct_value);
int c = ct_function(ct_value);
int d = rt_function(rt_value);
int e = rt_ct_function(rt_value);
int f = ct_function(rt_value); // ERROR: runtime value
constexpr int g = rt_function(ct_value); // ERROR: runtime function
constexpr int h = rt_ct_function(ct_value);
constexpr int i = ct_function(ct_value);
}
Pre C++20 workaround
You can enforce the use of it in a constant expression:
#include<utility>
template<typename T, T V>
constexpr auto ct() { return V; }
template<typename T>
constexpr auto func() {
return ct<decltype(std::declval<T>().value()), T{}.value()>();
}
template<typename T>
struct S {
constexpr S() {}
constexpr T value() { return T{}; }
};
template<typename T>
struct U {
U() {}
T value() { return T{}; }
};
int main() {
func<S<int>>();
// won't work
//func<U<int>>();
}
By using the result of the function as a template argument, you got an error if it can't be solved at compile-time.
A theoretical solution (as templates should be Turing complete) - don't use constexpr functions and fall back onto the good-old std=c++0x style of computing using exclusively struct template with values. For example, don't do
constexpr uintmax_t fact(uint n) {
return n>1 ? n*fact(n-1) : (n==1 ? 1 : 0);
}
but
template <uint N> struct fact {
uintmax_t value=N*fact<N-1>::value;
}
template <> struct fact<1>
uintmax_t value=1;
}
template <> struct fact<0>
uintmax_t value=0;
}
The struct approach is guaranteed to be evaluated exclusively at compile time.
The fact the guys at boost managed to do a compile time parser is a strong signal that, albeit tedious, this approach should be feasible - it's a one-off cost, maybe one can consider it an investment.
For example:
to power struct:
// ***Warning: note the unusual order of (power, base) for the parameters
// *** due to the default val for the base
template <unsigned long exponent, std::uintmax_t base=10>
struct pow_struct
{
private:
static constexpr uintmax_t at_half_pow=pow_struct<exponent / 2, base>::value;
public:
static constexpr uintmax_t value=
at_half_pow*at_half_pow*(exponent % 2 ? base : 1)
;
};
// not necessary, but will cut the recursion one step
template <std::uintmax_t base>
struct pow_struct<1, base>
{
static constexpr uintmax_t value=base;
};
template <std::uintmax_t base>
struct pow_struct<0,base>
{
static constexpr uintmax_t value=1;
};
The build token
template <uint vmajor, uint vminor, uint build>
struct build_token {
constexpr uintmax_t value=
vmajor*pow_struct<9>::value
+ vminor*pow_struct<6>::value
+ build_number
;
}
In the upcoming C++20 there will be consteval specifier.
consteval - specifies that a function is an immediate function, that is, every call to the function must produce a compile-time constant
Since now we have C++17, there is an easier solution:
template <auto V>
struct constant {
constexpr static decltype(V) value = V;
};
The key is that non-type arguments can be declared as auto. If you are using standards before C++17 you may have to use std::integral_constant. There is also a proposal about the constant helper class.
An example:
template <auto V>
struct constant {
constexpr static decltype(V) value = V;
};
constexpr uint64_t factorial(int n) {
if (n <= 0) {
return 1;
}
return n * factorial(n - 1);
}
int main() {
std::cout << "20! = " << constant<factorial(20)>::value << std::endl;
return 0;
}
Have your function take template parameters instead of arguments and implement your logic in a lambda.
#include <iostream>
template< uint64_t N >
constexpr uint64_t factorial() {
// note that we need to pass the lambda to itself to make the recursive call
auto f = []( uint64_t n, auto& f ) -> uint64_t {
if ( n < 2 ) return 1;
return n * f( n - 1, f );
};
return f( N, f );
}
using namespace std;
int main() {
cout << factorial<5>() << std::endl;
}
Lets say that you have a function which generates some security token for your application, such as some hash salt, or maybe a symetric or asymetric key.
Now lets say that you have this function in your C++ as a constexpr and that you generate keys for your build based on some information (like, the build number, a timestamp, something else).
You being a diligent programmer make sure and call this in the appropriate ways to ensure it's only called at compile time, and thus the dead stripper removes the code from the final executable.
However, you can't ever be sure that someone else isn't going to call it in an unsafe way, or that maybe the compiler won't strip the function out, and then your security token algorithm will become public knowledge, making it more easy for would be attackers to guess future tokens.
Or, security aside, let's say the function takes a long time to execute and you want to make sure it never happens during runtime and causes a bad user experience for your end users.
Are there any ways to ensure that a constexpr function can never be called at runtime? Or alternately, throwing an assert or similar at runtime would be ok, but not as ideal obviously as a compile error would be.
I've heard that there is some way involving throwing an exception type that doesn't exist, so that if the constexpr function is not deadstripped out, you'll get a linker error, but have heard that this only works on some compilers.
Distantly related question: Force constexpr to be evaluated at compile time
In C++20 you can just replace constexpr by consteval to enforce a function to be always evaluated at compile time.
Example:
int rt_function(int v){ return v; }
constexpr int rt_ct_function(int v){ return v; }
consteval int ct_function(int v){ return v; }
int main(){
constexpr int ct_value = 1; // compile value
int rt_value = 2; // runtime value
int a = rt_function(ct_value);
int b = rt_ct_function(ct_value);
int c = ct_function(ct_value);
int d = rt_function(rt_value);
int e = rt_ct_function(rt_value);
int f = ct_function(rt_value); // ERROR: runtime value
constexpr int g = rt_function(ct_value); // ERROR: runtime function
constexpr int h = rt_ct_function(ct_value);
constexpr int i = ct_function(ct_value);
}
Pre C++20 workaround
You can enforce the use of it in a constant expression:
#include<utility>
template<typename T, T V>
constexpr auto ct() { return V; }
template<typename T>
constexpr auto func() {
return ct<decltype(std::declval<T>().value()), T{}.value()>();
}
template<typename T>
struct S {
constexpr S() {}
constexpr T value() { return T{}; }
};
template<typename T>
struct U {
U() {}
T value() { return T{}; }
};
int main() {
func<S<int>>();
// won't work
//func<U<int>>();
}
By using the result of the function as a template argument, you got an error if it can't be solved at compile-time.
A theoretical solution (as templates should be Turing complete) - don't use constexpr functions and fall back onto the good-old std=c++0x style of computing using exclusively struct template with values. For example, don't do
constexpr uintmax_t fact(uint n) {
return n>1 ? n*fact(n-1) : (n==1 ? 1 : 0);
}
but
template <uint N> struct fact {
uintmax_t value=N*fact<N-1>::value;
}
template <> struct fact<1>
uintmax_t value=1;
}
template <> struct fact<0>
uintmax_t value=0;
}
The struct approach is guaranteed to be evaluated exclusively at compile time.
The fact the guys at boost managed to do a compile time parser is a strong signal that, albeit tedious, this approach should be feasible - it's a one-off cost, maybe one can consider it an investment.
For example:
to power struct:
// ***Warning: note the unusual order of (power, base) for the parameters
// *** due to the default val for the base
template <unsigned long exponent, std::uintmax_t base=10>
struct pow_struct
{
private:
static constexpr uintmax_t at_half_pow=pow_struct<exponent / 2, base>::value;
public:
static constexpr uintmax_t value=
at_half_pow*at_half_pow*(exponent % 2 ? base : 1)
;
};
// not necessary, but will cut the recursion one step
template <std::uintmax_t base>
struct pow_struct<1, base>
{
static constexpr uintmax_t value=base;
};
template <std::uintmax_t base>
struct pow_struct<0,base>
{
static constexpr uintmax_t value=1;
};
The build token
template <uint vmajor, uint vminor, uint build>
struct build_token {
constexpr uintmax_t value=
vmajor*pow_struct<9>::value
+ vminor*pow_struct<6>::value
+ build_number
;
}
In the upcoming C++20 there will be consteval specifier.
consteval - specifies that a function is an immediate function, that is, every call to the function must produce a compile-time constant
Since now we have C++17, there is an easier solution:
template <auto V>
struct constant {
constexpr static decltype(V) value = V;
};
The key is that non-type arguments can be declared as auto. If you are using standards before C++17 you may have to use std::integral_constant. There is also a proposal about the constant helper class.
An example:
template <auto V>
struct constant {
constexpr static decltype(V) value = V;
};
constexpr uint64_t factorial(int n) {
if (n <= 0) {
return 1;
}
return n * factorial(n - 1);
}
int main() {
std::cout << "20! = " << constant<factorial(20)>::value << std::endl;
return 0;
}
Have your function take template parameters instead of arguments and implement your logic in a lambda.
#include <iostream>
template< uint64_t N >
constexpr uint64_t factorial() {
// note that we need to pass the lambda to itself to make the recursive call
auto f = []( uint64_t n, auto& f ) -> uint64_t {
if ( n < 2 ) return 1;
return n * f( n - 1, f );
};
return f( N, f );
}
using namespace std;
int main() {
cout << factorial<5>() << std::endl;
}
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.
Imagine that you have a lot of classes with a lot of different template parameters. Every class has a method static void f(). You want to collect all these function pointers in a list L.
A run-time solution would be easy:
typedef void (*p)();
std::vector<p> L;
int reg (p x) { static int i = 0; L.push_back(x); return i++; } // also returns an unique id
template <typename T> struct regt { static int id; };
template <typename T> int regt<T>::id = reg (T::f);
template < typename ... T > struct class1 : regt< class1<T...> > { static void f(); };
template < typename ... T > struct class2 : regt< class2<T...> > { static void f(); };
// etc.
The compiler knows all f()s of all instantiated classes at compile-time. So, theoretically it should be possible to generate such a list (a const std::array<p, S> L with some S) as a compile-time constant list. But how? (C++0x solutions are welcome, too).
Why do I need this?
On an architecture with only 256 kB (for code and data), I need to generate objects for incoming ids of classes. Existing serialization frameworks or the run-time solution above are unnecessarily big. Without templates a compile-time solution would be easy, but I want to keep all the advantages templates offer.
Manually
The simplest thing that you can do is just roll the code manually, I don't think that there is much that can be used to your advantage from the templates, so I will use plain classes, where A, B... stand for particular instantiations of your types. That allows for compile time initialization of the types, at the cost of having to remember to update the lookup table whenever a new type is added to the system:
typedef void (*function_t)();
function_t func[] = {
&A::f,
&B::f,
&C::f
};
I would recommend this, from a maintenance point of view. Automating the system will make the code much harder to understand and maintain in the future.
Macros
The simple most automated one, which will probably generate less code is a macro generation system is just using macros. Since this first approach will use extensive use of macros, I will generate the functions automatically, as you did in the previous question. You can remove that part of code if you have (hopefully) given up the path of full code generation through macros.
To avoid having to retype the names of the types in different contexts you can define a macro with all the data you need for any context, and then use other macros to filter what is to be used (and how) in each particular context:
// This is the actual list of all types, the id and the code that you were
// generating in the other question for the static function:
#define FOREACH_TYPE( macro ) \
macro( A, 0, { std::cout << "A"; } ) \
macro( B, 1, { std::cout << "B"; } ) \
macro( C, 2, { std::cout << "C"; } )
// Now we use that recursive macro to:
// Create an enum and calculate the number of types used
#define ENUM_ITEM( type, id, code ) \
e_##type,
enum AllTypes {
FOREACH_TYPE( ENUM_ITEM )
AllTypes_count
};
#undef ENUM_ITEM
// Now we can create an array of function pointers
typedef void (*function_t)();
function_t func[ AllTypes_count ];
// We can create all classes:
#define CREATE_TYPE( type, the_id, code ) \
struct type {\
static const int id = the_id; \
static void func() code\
};
FOREACH_TYPE( CREATE_TYPE )
#undef CREATE_TYPE
// And create a function that will
#define REGISTER_TYPE( type, id, code ) \
func[ i++ ] = &type::func;
void perform_registration() {
int i = 0;
FOREACH_TYPE( REGISTER_TYPE );
};
#undef REGISTER_TYPE
// And now we can test it
int main() {
perform_registration();
for ( int i = 0; i < AllTypes_count; ++i ) {
func[ i ]();
}
}
This is, on the other hand a maintenance nightmare, quite fragile and hard to debug. Adding new types is trivial, just add a new line to the FOREACH_TYPE macro and you are done... and the best of lucks once something fails...
Templates and metaprogramming
On the other hand, using templates you can get close but you cannot get to the single point of definition for the types. You can automate some of the operations in different ways, but at the very least you will need to define the types themselves and add them to a typelist to get the rest of the functionality.
Simplifying the definition of the actual type_list with C++0x code you can start by defining the types and then creating the type_list. If you want to avoid using C++0x, then take a look at the Loki library, but with C++0x a type list is simple enough:
template <typename ... Args> type_list {}; // generic type list
typedef type_list< A, B, C, D > types; // our concrete list of types A, B, C and D
// this is the only source of duplication:
// types must be defined and added to the
// type_list manually [*]
Now we need to use some metaprogramming to operate on the type list, we can for example count the number of elements in the list:
template <typename List> struct size; // declare
template <typename T, typename ... Args> // general case (recursion)
struct size< type_list<T,Args...> > {
static const int value = 1 + size< type_list<Args...>::value;
};
template <> // stop condition for the recursion
struct size< type_list<> > {
static const int value = 0;
};
Having the size of the type list is a first step in our problem, as it allows us to define an array of functions:
typedef void (*function_t)(); // signature of each function pointer
struct registry {
static const int size = ::size< types >::value;
static const function_t table[ size ];
};
function_t registry::table[ registry::size ]; // define the array of pointers
Now we want to register the static functions from each particular type in that array, and for that we create an auxiliar function (encapsulated as a static function in a type to allow for partial specializations). Note that this concrete part is designed to be run during initialization: it will NOT be compile time, but the cost should be trivial (I would be more worried on the binary size with all the templates):
template <typename T, int N> // declaration
struct register_types_impl;
template <typename T, typename ... Args, int N> // general recursion case
struct register_types_impl< type_list<T,Args...>, N> {
static int apply() {
registry::table[ N ] = &T::f; // register function pointer
return register_types_impl< type_list<Args...>, N+1 >;
}
};
template <int N> // stop condition
struct register_types_impl< type_list<>, int N> {
static int apply() { return N; }
};
// and a nicer interface:
int register_types() {
register_types_impl< types, 0 >();
}
Now we need an id function that maps our types to the function pointer, which in our case is the position of the type in the type list
template <typename T, typename List, int N> // same old, same old... declaration
struct id_impl;
template <typename T, typename U, typename ... Args, int N>
struct id_impl< T, type_list<U, Args...>, N > { // general recursion
static const int value = id_impl< T, type_list<Args...>, N+1 >;
};
template <typename T, typename ... Args, int N> // stop condition 1: type found
struct id_impl< T, type_list<T, Args...>, N> {
static const int value = N;
};
template <typename T, int N> // stop condition 2: type not found
struct id_impl< T, type_list<>, N> {
static const int value = -1;
}
// and a cleaner interface
template <typename T, typename List>
struct id {
static const int value = id_impl<T, List, 0>::value;
};
Now you just need to trigger the registration at runtime, before any other code:
int main() {
register_types(); // this will build the lookup table
}
[*] Well... sort of, you can use a macro trick to reuse the types, as the use of macros is limited, it will not be that hard to maintain/debug.
The compiler knows all f()s of all instantiated classes at compile-time.
There's your mistake. The compiler knows nothing about template instantiations in other compilation units. It should now be pretty obvious why the number of instantiations isn't a constant integral expression that could be used as a template argument (and what if std::array was specialized? Halting Problem ahead!)