Initialise static const int with static function - c++

I have a template class with some integers as arguments. One static const integer (call it Length) of this class needs to be calculated based on the arguments. The calculation does need a loop (as far as I know) so a simple expression won't help.
static int setLength()
{
int length = 1;
while (length <= someTemplateArgument)
{
length = length << 1;
}
return length;
}
The returned length should be used to init Length. Lengthis used as a fixed length of an array so I need it to be constant.
Is there a solution for this issue? I know that constexp could help but I can't use C11 or later.

Using metaprogramming. Implementation of C++11 enable_if taken from cppreference.com
#include <iostream>
template<bool B, class T = void>
struct enable_if {};
template<class T>
struct enable_if<true, T> { typedef T type; };
template <int length, int arg, typename = void>
struct length_impl
{
static const int value = length_impl<(length << 1), arg>::value;
};
template <int length, int arg>
struct length_impl<length, arg, typename enable_if<(length > arg)>::type>
{
static const int value = length ;
};
template <int arg>
struct length_holder
{
static const int value = length_impl<1, arg>::value;
};
template<int n>
struct constexpr_checker
{
static const int value = n;
};
int main()
{
std::cout << constexpr_checker< length_holder<20>::value >::value;
}

Related

Template non-type parameter with different types

Let's assume an input template parameter T may or may not have internal variable bar. I am trying to write a struct that returns the value of bar when we have it, and returns some constant when we don't. Here is my attempt:
struct A {
static constexpr unsgined int bar = 20;
hasBar = true;
};
struct B {
hasBar = false;
};
template <typename T, typename std::enable_if<T::hasBar, int>::type>
struct getBar {
static constexpr unsigned int bar = T::bar;
};
template <typename T, typename std::enable_if<!T::hasBar, int>::type>
struct getBar {
static constexpr unsigned int bar = 0;
};
int main() {
getBar<A>::bar; // Expect 20
getBar<B>::bar; //Expect 0
}
I cannot compile this code with C++14. The compiler complains that: "template non-type parameter has a different type".
Why we have such an error and how can I address it?
Class templates can't be overloaded (like function templates); You can use specialization instead. e.g.
template <typename T, typename = void>
struct getBar {
static constexpr unsigned int bar = 0;
};
template <typename T>
struct getBar<T, std::enable_if_t<T::hasBar>> {
static constexpr unsigned int bar = T::bar;
};
LIVE
You can detect whether ::bar exists directly without the need for hasbar
something like ...
#include <type_traits>
#include <iostream>
struct A {
static constexpr unsigned int bar = 20;
};
struct B {
};
template <typename T,typename=void>
struct getBar {
static constexpr unsigned int bar = 0;
};
template <typename T>
struct getBar<T,std::void_t<decltype(T::bar)>> {
static constexpr unsigned int bar = T::bar;
};
int main() {
std::cout << getBar<A>::bar << std::endl; // Expect 20
std::cout << getBar<B>::bar << std::endl; //Expect 0
}
Demo
Another solution that doesn't needs hasBar but simply detect the presence of bar (and also maintain the original type of bar, if different from int)
struct A
{ static constexpr unsigned int bar = 20; };
struct B
{ };
template <typename T>
constexpr auto getBarHelper (int) -> decltype( T::bar )
{ return T::bar; }
template <typename T>
constexpr int getBarHelper (long)
{ return 0; }
template <typename T>
struct getBar
{ static constexpr auto bar { getBarHelper<T>(0) }; };
int main()
{
static_assert( 20u == getBar<A>::bar, "!" );
static_assert( 0 == getBar<B>::bar, "!" );
}

Nested Template Classes

I want to be able to create a generic nested template such that I can find the total size of all classes. To start, imagine for classes A, B, C, etc... each of which have a mSize member, and GetSize() function. I do the following process:
int main()
{
using Abc = A<B<C<>>>; // Imagine it is defined similarly to this for now.
Abc abc;
std::cout << abc.GetSize() << std::endl;
// For abc.GetSize(), this will do the following:
// 1. Go into A::GetSize().
// 2. This will return A::mSize + B::GetSize()
// 3. This will go into B::GetSize()
// 4. This will return B::mSize + C::GetSize()
// 5. Etc
// Overall, we will have the total size of A+B+C as
// A::mSize + B::mSize + C::mSize.
return 0;
}
It will recursively go through each template class until the end and call GetSize(). My current attempts to do so have been using template-templates and variadic templates.
template <template<typename> class First, template<typename> class ...Args>
class A
{
public:
int GetSize() const
{
First<Args...> foo;
return mSize + foo.GetSize();
}
private:
int mSize{1};
};
template <template<typename> class First, template<typename> class ...Args>
class B
{
public:
int GetSize() const
{
First<Args...> foo;
return mSize + foo.GetSize();
}
private:
int mSize{2};
};
template <template<typename> class First, template<typename> class ...Args>
class C
{
public:
int GetSize() const
{
First<Args...> foo;
return mSize + foo.GetSize();
}
private:
int mSize{3};
};
This obviously has not worked. I would really like to be able to achieve the process described in int main().
Notes:
These classes don't necessarily have to be included, or be in order. We could have A<C> or B<E<C<F<>>>>. Ideally, it can be infinitely long.
I don't want to use polymorphism, wanting it to be resolved at runtime. I could have them all inherit from the same class, create a std::vector<Parent*>, push_back each child class, and iterate through using GetSize(). It would be nice to be able to define unique types such as A<B<>>, A<B<C<>>>, etc.
Since your mSize is the same for all instance, your method should be static, and since it looks like it is a constant, it should be a constexpr.
Here is an implementation that uses a general template and then partially instantiate it with specific sizes:
template <int Size, typename T>
struct Holder {
static constexpr int GetSize() {
return Size + T::GetSize();
}
};
template <int Size>
struct Holder<Size, void> {
static constexpr int GetSize() {
return Size;
}
};
template <typename T = void>
using A = Holder<1, T>;
template <typename T = void>
using B = Holder<2, T>;
template <typename T = void>
using C = Holder<3, T>;
Then you can test:
using AB = A<B<>>;
using ABC = A<B<C<>>>;
static_assert(AB::GetSize() == 1 + 2, "Oops!");
static_assert(ABC::GetSize() == 1 + 2 + 3, "Oops!");
Of course you can make A, B, C, ... extends Holder instead of partially instantiate it if you need it.
You could do something like:
#include <iostream>
#include <type_traits>
using namespace std;
template <class T>
struct A {
static constexpr int size = 1;
using inner_type = T;
};
template <class T>
struct B {
static constexpr int size = 2;
using inner_type = T;
};
//template <class T>
struct C {
static constexpr int size = 3;
using inner_type = void;
};
template <class T, class = void>
struct TotalSizeGetter {
static constexpr int get() {
return T::size + TotalSizeGetter<typename T::inner_type>::get();
}
};
template <class T>
struct TotalSizeGetter<T, typename enable_if<is_void<typename T::inner_type>::value>::type> {
static constexpr int get() {
return T::size;
}
};
int main() {
cout << TotalSizeGetter<A<B<C>>>::get() << endl;
}
This uses c++11 constexpr and enable_if but I see this is not a limitation as you use term variadic templates in your question...

Passing a constexpr function to use at compile time

I'm trying to make a simple way to generate std::array's at compile time. It's been a struggle so far to figure out a good way to pass a constexpr function in at compile time. The workaround I have found so far is like this.
#include <iostream>
#include <array>
namespace a {
constexpr int f(const int & i) { return i * i * i;}
#include "generate_with_function.hpp"
}
int main()
{
auto arr = a::generator<false,10,0>::array;
for (auto i : arr) {
std::cout << i << " ";
}
return 0;
}
this basically assumes you will define a function called f and I wrapped it in a namespace incase I wanted to do a different one. I wanted to know if there is a more clever way to pass in the function and use it at compile time. Also here is the code that makes the list.
template <bool B, size_t Count,int ... Nums>
struct generator;
template <size_t Count>
struct generator<false,Count,0>
{
constexpr static std::array<int,Count> array
= generator<false,Count,1,f(0)>::array;
};
template <size_t Count, int Current, int ... Results>
struct generator<false,Count,Current, Results...>
{
constexpr static std::array<int,Count> array
= generator<Current+1==Count,Count,Current+1,f(Current), Results...>::array;
};
template <size_t Count, int Current, int ... Results>
struct generator<true,Count,Current,Results...>
{
constexpr static std::array<int,Count> array{{Results...}};
};
and before you ask no I don't actually have a real need for this.
As noted by #us2012 I should be specific about what I would rather have.
nowrapping in namespace
having to write the function but not actually passing it anywhere
and not requiring the function to be named f
You can actually use the function as a template parameter, here called Gen:
template <bool B, size_t Count, int Current, int Gen(size_t), int ... Nums>
struct generator;
template <size_t Count, int Current, int Gen(size_t), int ... Results>
struct generator<false,Count,Current, Gen, Results...>
{
constexpr static std::array<int,Count> array
generator<Current+1==Count,Count,Current+1,Gen,
Gen(Current), Results...>::array;
};
template <size_t Count, int Current, int Gen(size_t), int ... Results>
struct generator<true,Count,Current,Gen,Results...>
{
constexpr static std::array<int,Count> array{{Results...}};
};
With this it actually works to pass a constexpr function to the template (if the type matches exactly):
// helper to hide the "internal" template parameters
template <size_t Count, int Gen(size_t)>
struct gen {
constexpr static std::array<int, Count> array = generator<false, Count, 0, Gen>::array;
};
constexpr int f(size_t i) { return i * i * i; }
int main()
{
auto arr = gen<10,f>::array;
for (auto i : arr) {
std::cout << i << " ";
}
return 0;
}
You can also switch around the Gen(Current) and Results... parameters to get the values at the "correct" array indexes.

Creating parameters pack based on another pack from template arguments

Suppose there are several template classes (structures), objects of which form the sequence - let's call them N_mod(N - specifier for particular class), and special class, that defines the first element in the sequence - First_mod. Each class, except First_mod, has its own "interface builder" - N_builder - template class:
template<int targ>
struct First_mod //First element in sequence - without appropriate builder interface
{ };
//Let's consider two types of N_mod - A_mod and B_mod
template<int targ, int param>
struct A_mod
{ };
template<int param>
struct A_builder//Builder for A_mod objects
{ };
template<int targ, int param>
struct B_mod
{ };
template<int param>
struct B_builder//Builder for B_mod objects
{ };
Now I need to generate sequence of First_mod and N_mod objects from existing sequense of appropriate N_builders in accordance with simple rule:
if N_Mod(i) equals A_mod then targ(i) = param(i) - targ(i-1),
else(i.e. N_Mod(i) equals B_mod) targ(i) = param(i) * targ(i-1)
My sketches for clarity:
template<typename...builders>
struct mod_seq_gen
{
typedef /*generated First_mod, A_mod and B_mod sequence pack. How to do it?*/ modseq;
};
template<typename...builders>
struct Container
{
std::tuple</*here must be mod-sequence generator that creates
mod parameters pack and unpacks them:*/
mod_seq_gen<builders...>::modseq
> mod_sequence;
};
int main()
{
/*In this case must be generated next sequence and stored in
* mod_sequence tuple:
* First_mod<3> - A_mod<5-3, 5> - B_mod<2*(5-3), 2>
*/
Container<First_mod<3>, A_builder<5>, B_builder<2>> obj;
}
I'm asking to help in the implementation of mod_seq_gen, or some other tips for the whole task.
First I'll dump the (compiling) solution:
#include <tuple>
#include <utility>
#include <iostream>
template<int targ>
struct First_mod //First element in sequence - without appropriate builder interface
{ void print() { std::cout << "First_mod["<<targ<<"]" << std::endl; } };
//Let's consider two types of N_mod - A_mod and B_mod
template<int targ, int param>
struct A_mod
{ void print() { std::cout << "A_mod["<<targ<<", "<<param<<"]" << std::endl; } };
template<int param>
struct A_builder//Builder for A_mod objects
{
// publish the template parameter (not necessary)
static const int param_value = param;
// provide a way to compute the current targ
static constexpr int calc_targ(int prev_targ)
{
return param - prev_targ;
}
// provide a way to build the type
template < int targ >
using type = A_mod<targ, param>;
};
template<int targ, int param>
struct B_mod
{ void print() { std::cout << "B_mod["<<targ<<", "<<param<<"]" << std::endl; } };
template<int param>
struct B_builder//Builder for B_mod objects
{
static const int param_value = param;
static constexpr int calc_targ(int prev_targ)
{
return prev_targ * param;
}
template < int targ >
using type = B_mod<targ, param>;
};
// just a helper, wonder if there's something in the Standard Library o.O
template < typename... Tuples >
using tuple_cat_types = decltype(tuple_cat( std::declval<Tuples>()... ));
// the generator of the tuple
template < typename TFirst_mod, typename... TBuilders >
struct gen;
// restrict the first type to a specialization of `First_mod`
// isn't necessary, strictly speaking. We just need the first targ.
// Could as well require a nested `static const int targ = ..;`
template < int first_targ, typename... TBuilders >
struct gen < First_mod<first_targ>, TBuilders... >
{
// recursive helper for the types to be built
// general case for no template arguments in the pack
template < int prev_targ, typename... TBuilders2 >
struct helper { using type = std::tuple<>; };
// specialized case for recursion
// note: the recursion here occurs as a nested typedef, not inheritance
// (simplifies use of calculated targ)
template < int prev_targ, typename TBuilder, typename... TBuilders2 >
struct helper<prev_targ, TBuilder, TBuilders2...>
{
// build type using builder
static const int targ = TBuilder::calc_targ(prev_targ);
using built_type = typename TBuilder::template type<targ>;
// recurse
using further_types = typename helper<targ, TBuilders2...>::type;
// concatenate tuple
using type = tuple_cat_types<std::tuple<built_type>, further_types>;
};
// concatenate tuple with First_mod
using type = tuple_cat_types<std::tuple<First_mod<first_targ>>,
typename helper<first_targ, TBuilders...>::type>;
};
int main()
{
gen<First_mod<3>, A_builder<5>, B_builder<2>>::type x;
static_assert(std::tuple_size<decltype(x)>::value == 3, "!");
std::get<0>(x).print();
std::get<1>(x).print();
std::get<2>(x).print();
}
Slightly easier with a builder for First_mod:
template<int param>
struct First_builder
{
static constexpr int calc_targ(int /* discarded */)
{
return param;
}
template < int targ >
using type = First_mod<targ>;
};
/* ... */
// the generator of the tuple
template < int prev_targ, typename... TBuilders >
struct gen
{ using type = std::tuple<>; };
template < int prev_targ, typename TBuilder, typename... TBuilders2 >
struct gen<prev_targ, TBuilder, TBuilders2...>
{
// build type using builder
static const int targ = TBuilder::calc_targ(prev_targ);
using built_type = typename TBuilder::template type<targ>;
// recurse
using further_types = typename gen<targ, TBuilders2...>::type;
// concatenate tuple
using type = tuple_cat_types<std::tuple<built_type>, further_types>;
};
int main()
{
const int discarded = 0;
gen<discarded, First_builder<3>, A_builder<5>, B_builder<2>>::type x;
static_assert(std::tuple_size<decltype(x)>::value == 3, "!");
std::get<0>(x).print();
std::get<1>(x).print();
std::get<2>(x).print();
}

Easiest way to get the N-th argument of a variadic templated class?

I wonder what is the easiest and more common way to get the N-th parameter of a variadic templated class at compile-time (The returned value has to be as a static const for the compiler in order to do some optimizations). Here is the form of my templated class :
template<unsigned int... T> MyClass
{
// Compile-time function to get the N-th value of the variadic template ?
};
Thank you very much.
EDIT : As MyClass will contain more than 200 functions, I can't specialize it. But I can specialize a struct or a function inside MyClass.
EDIT : Final solution derived from the validated answer :
#include <iostream>
template<unsigned int... TN> class MyClass
{
// Helper
template<unsigned int index, unsigned int... remPack> struct getVal;
template<unsigned int index, unsigned int In, unsigned int... remPack> struct getVal<index, In,remPack...>
{
static const unsigned int val = getVal<index-1, remPack...>::val;
};
template<unsigned int In, unsigned int...remPack> struct getVal<1,In,remPack...>
{
static const unsigned int val = In;
};
// Compile-time validation test
public:
template<unsigned int T> inline void f() {std::cout<<"Hello, my value is "<<T<<std::endl;}
inline void ftest() {f<getVal<4,TN...>::val>();} // <- If this compile, all is OK at compile-time
};
int main()
{
MyClass<10, 11, 12, 13, 14> x;
x.ftest();
return 0;
}
"Design by induction" should come out something like this:
template<unsigned int N, unsigned int Head, unsigned int... Tail>
struct GetNthTemplateArgument : GetNthTemplateArgument<N-1,Tail...>
{
};
template<unsigned int Head, unsigned int... Tail>
struct GetNthTemplateArgument<0,Head,Tail...>
{
static const unsigned int value = Head;
};
template<unsigned int... T>
class MyClass
{
static const unsigned int fifth = GetNthTemplateArgument<4,T...>::value;
};
Here is another way to do it:
template<unsigned int index, unsigned int In, unsigned int... remPack> struct getVal
{
static const unsigned int val = getVal<index-1, remPack...>::val;
};
template<unsigned int In, unsigned int...remPack> struct getVal<0,In,remPack...>
{
static const unsigned int val = In;
};
template<unsigned int... T> struct MyClass
{
//go to any arg by : getVal<Some_Unsigned_Index, T...>::val;
};
Test: http://liveworkspace.org/code/4a1a9ed4edcf931373e7ab0bf098c847
and if you get sting by "cannot expand 'T...' into a fixed-length argument list" http://ideone.com/YF4UJ
Here is what you can also do
template<int N, typename T, T ... Ts>
struct GetN {
constexpr T values[sizeof...(Ts)] = { Ts... };
static const T value = values[N];
};
template<int N, typename T, T ... Ts>
constexpt T GetN<N, T, Ts...>::values[sizeof...(Ts)];
Then you can simply do
template<int N, unsigned int... T> struct MyClass {
static const unsigned int value = GetN<N, unsigned int, T...>::value;
};
Yet another simple method:
#include <array>
template<int... Args>
class Foo {
public:
static constexpr int Element(int index) {
return std::array<int, sizeof...(Args)>{ Args... }[index];
}
int First = Element(0);
int Second = Element(1);
};
int main() {
return Foo<0, 1>::Element(0);
}
// or just
int Nth = std::array<int, sizeof...(Args)>{ Args... }[N];
BTW, here is a general method of extracting N-th argument of any variadic template:
#include <tuple>
template<typename... Args>
class Foo {
public:
template <int N>
using Nth = typename std::remove_reference<decltype(std::get<N>(std::declval<std::tuple<Args...>>()))>::type;
};
int main() {
Foo<int, float>::Nth<1> val = 3.14159f;
return 0;
}