complex constexpr alternatives - templates

Consider
typedef std::complex<double> Complex;
Complex ComplexExpresion(int a) {return Complex(0,-a);}
Since one cannot write
template<typename D>
struct A
{
static constexpr Complex value = ComplexExpresion(D::value);
};
as an alternative one writes
template<typename D>
struct B
{
static const Complex value;
};
template<typename D>
const Complex B<D>::value = ComplexExpresion(D::value);
Consider now
template<typename D, int N>
struct C;
template<typename D>
struct C<D,1>
{
static const Complex value;
};
template<typename D>
const Complex C<D,1>::value = B<D>::value;
For some reasone
struct Data
{
static auto constexpr value =2;
};
int main()
{
using C = C<Data,1>;
std::cout << C::value;
}
prints the correct value(which is (0,-2) ) here but the same code prints (0,0) when complied by MSVC++
I have 2 questions
1) why it is so on MSVC++ and is there known workaround?
2) is there better alternative for struct A than struct B which is not exactly the same thing...

Looks like a compiler bug unless I'm missing something. This isn't really an answer, just sharing what I found. This is the smallest example I could deduce that exhibits the issue:
#include <iostream>
// using function is important
int func() { return 1; }
// template is imporant
template<class D>
struct B
{
static const int value;
};
// defined outside block is important
template<class D>
const int B<D>::value = func();
// going through C is important
struct C
{
static const int value;
};
const int C::value = B<int>::value;
int main()
{
// should print 1 but prints 0
std::cout << C::value << std::endl;
}
surprisingly this also trips up clang unless I specify func as constexpr or specify -stdlib=libc++ (at least on coliru)
I guess you can fix your issue by skipping one of the bits above. You can do static constexpr Complex value = ComplexExpresion(D::value); if you mark ComplexEspression as constexpr.

Related

How to instantiate a list of types for compile-time/static polymorphism

I'm implementing a compile time dispatcher which makes use of static polymorphism and metaprogramming.
I have a list of types which I would like to instantiate into a runtime std::array.
struct Test
{
typedef std::integral_constant<int,0> nop;
typedef std::integral_constant<int,1> A;
typedef std::integral_constant<int,2> B;
typedef std::integral_constant<int,3> C;
using list = mp_list<A, B, C>; // mp_list expands to: template<A, B, C> struct {};
struct Things{
int (Test::*process)(int foo, float bar);
const std::string key;
int something;
float other;
};
typedef std::array<Things, mp_size<list>::value> Thing_list;
Thing_list thing_list;
template<typename T=nop> int process(int foo, float bar);
// stuff...
Test();
}
In the above code, mp_list is simply a variadic template which 'expands' to struct<A, B, C> mp_list. And likewise, mp_size gives an mp implementation of the sizeof.
As can be inferred, the Thing_list is an array with a compile-time known size.
I can then specialize a template function like so:
template<> int process<Test::B>(int foo, float bar){ /* do stuff */ };
to achieve compile-time polymorphism.
The above code works well, except that to initialize it, I am stuck at doing this in the constructor:
Test::Test() thing_list({{{&Test::process<A>, "A"}, // this all should be achieved through meta-programming
{&Test::process<B>, "B"},
{&Test::process<C>, "C"}}}} )
{
// stuff
}
There are two things I'm unable to get right:
I would like to have a MP based initialization of the list. As I update the list definition in the declaration, I would like my initialization to automatically reflect that list type.
I would also like to avoid having to duplicate the name of the type as a string literal. I have tried to use something like integral_constant but the use of const char* as a template parameter seems to be forbidden. I am left to having to duplicate declaration (triplicate, really).
This answer is almost the solution: it takes a list of types and instantiates them like so:
static std::tuple<int*, float*, foo*, bar*> CreateList() {
return { Create<int>(), Create<float>(), Create<foo>(), Create<bar>() };
}
However, I'm stuck on converting from std::tuple to std::array.
The main question is #1. Bonus for #2 without using #define based trickery.
If anyone cares: this code is destined for embedded software. There are dozens of different types, and importantly, each type (e.g. A, B, C) will have an identically structured configuration to be loaded from memory (e.g. under a configuration key for "A") - hence the reason of wanting to have access to the string name of the type at runtime.
Not sure to understand what do you exactly want but...
Given that you can use at least C++17 (for auto template parameters), you can define outside your class some variables as
static constexpr char nops[] = "NOP";
static constexpr char A[] = "A";
static constexpr char B[] = "B";
static constexpr char C[] = "C";
Then a simple wrapper that accept nops, A, B, etc. as template parameters
template <auto val>
struct wrap
{ };
Then a using that, given a variadic list of template value parameters, create a mp_list of wrap types
template <auto ... vals>
using wrapper = mp_list<wrap<vals>...>;
At this point... I suppose that, inside Test, you can define nop and list as follows
using nop = wrap<nops>;
using list = wrapper<A, B, C>;
Using delegating constructor, meta-programming way to initialize your thing_list could be the following
template <auto ... vals>
Test (mp_list<wrap<vals>...>)
: thing_list{{{&Test::process<wrap<vals>>, vals}...}}
{ }
Test () : Test{list{}}
{ }
If you modify the list adding a D parameter (where D is the "D" literal)
using list = wrapper<A, B, C, D>;
automagically the you get an additional {&Test::process<wrap<D>>, D} element in your thing_list.
The following is a full compiling C++17 example
#include <array>
#include <string>
#include <type_traits>
template <typename...>
struct mp_list
{ };
template <typename>
struct mp_size;
template <typename ... Ts>
struct mp_size<mp_list<Ts...>>
: public std::integral_constant<std::size_t, sizeof...(Ts)>
{ };
static constexpr char nops[] = "NOP";
static constexpr char A[] = "A";
static constexpr char B[] = "B";
static constexpr char C[] = "C";
template <auto val>
struct wrap
{ };
template <auto ... vals>
using wrapper = mp_list<wrap<vals>...>;
struct Test
{
using nop = wrap<nops>;
using list = wrapper<A, B, C>;
struct Things
{
int (Test::*process)(int foo, float bar);
const std::string key;
// int something;
// float other;
};
using Thing_list = std::array<Things, mp_size<list>::value>;
Thing_list thing_list;
template<typename T=nop> int process(int foo, float bar)
{ return 0; }
template <auto ... vals>
Test (mp_list<wrap<vals>...>)
: thing_list{{{&Test::process<wrap<vals>>, vals}...}}
{ }
Test () : Test{list{}}
{ }
};
int main ()
{
Test t;
}
I would suggest changing the typedefs for A, B and C to struct so you can define the string inside them.
struct A {
static constexpr int value = 1;
static constexpr char name[] = "A";
};
// Same for B and C
using list = mp_list<A, B, C>;
Then you can create a make_thing_list
template <typename... T>
static std::array<Things, sizeof...(T)> make_thing_list(mp_list<T...>) {
return {{{&Test::process<T>, T::name}...}};
}
auto thing_list = make_thing_list(list{});
Complete example
#include <string>
#include <array>
#include <iostream>
template <typename... T>
struct mp_list {};
struct Test
{
struct nop {
static constexpr int value = 0;
static constexpr char name[] = "nop";
};
struct A {
static constexpr int value = 1;
static constexpr char name[] = "A";
};
struct B {
static constexpr int value = 2;
static constexpr char name[] = "B";
};
struct C {
static constexpr int value = 3;
static constexpr char name[] = "C";
};
using list = mp_list<A, B, C>; // mp_list expands to: template<A, B, C> struct {};
struct Things{
int (Test::*process)(int foo, float bar);
const std::string key;
int something;
float other;
};
template <typename... T>
static std::array<Things, sizeof...(T)> make_thing_list(mp_list<T...>) {
return {{{&Test::process<T>, T::name}...}};
}
using Thing_list = decltype(make_thing_list(list{}));
Thing_list thing_list = make_thing_list(list{});
template<typename T=nop> int process(int foo, float bar) {
return T::value;
}
// stuff...
Test() {}
};
int main() {
Test t;
static_assert(std::is_same_v<decltype(t.thing_list), std::array<Test::Things, 3>>);
for (auto& thing : t.thing_list) {
std::cout << thing.key << (t.*thing.process)(1, 1.0) << '\n';
}
}

Template template parameter with typed parameters?

The following code does not compile. Is it even possible to pass an instance of Configuration<t, u> as a template parameter? (to profit from optimization of constant expressions)
API:
template <int t, bool u>
struct Configuration {
static constexpr int commonValue = t;
static constexpr bool debug = u;
};
template <
template<int t, bool u> Configuration<t, u> &conf,
int x
>
class A {
public:
int doSomething() {
if (conf.debug) { // Optimize away if false
// ...
}
return x * conf.commonValue; // Optimize to e.g. 6 with `conf.commonValue` =
// 3, `x` = 2
}
};
The user of the API should be able to do:
int main() {
static constexpr Configuration<3, false> conf;
A<conf, 2> a;
A<conf, 5> b;
A<conf, 8> c;
std::cout << a.doSomething() << std::endl; // 6 (evaluated at compile time!)
std::cout << b.doSomething() << std::endl; // 15
std::cout << c.doSomething() << std::endl; // 24
}
Since the attributes of Configuration are static, you should use a template type parameter1:
template <class ConfT, int x>
class A {
public:
int doSomething() {
if (ConfT::debug) { // Optimize away if false
}
return x * ConfT::commonValue;
}
};
And then:
// Alias (not required):
using conf = Configuration<3, false>;
A<conf, 2> a;
A<conf, 3> b;
If you want non-static members, I don't think this is doable pre-C++17 (without passing template parameters of Configuration to A), but in C++17 you could do1:
template <auto const& conf, int x>
class A {
public:
int doSomething() {
if (conf.debug) { // Optimize away if false
}
return x * conf.commonValue;
}
};
But note that you can only pass references to variables with static storage duration.
1 In the first case, you can restrict the type to Configuration<...> by specializing A, in the second case, you can restrict the type of conf using an extra template parameter with std::enable_if.
You should also make the attributes constexpr in Configuration, not simply const:
template <int t, bool u>
struct Configuration {
static constexpr int commonValue = t;
static constexpr bool debug = u;
};

variadic template only using type parameter

I would like to do something like this:
#include <iostream>
class a {
public:
a() : i(2) {}
template <typename ...ts>
void exec() {
f<ts...>();
std::cout << "a::()" << std::endl;
}
int i;
private:
template <typename t>
void f() {
i += t::i;
}
template <typename t, typename ...ts>
void f() {
f<t>();
f<t, ts...>();
}
};
struct b {
static const int i = -9;
};
struct c {
static const int i = 4;
};
int main()
{
a _a;
_a.exec<b,c>();
std::cout << _a.i << std::endl;
}
The idea is to get the same information from a group of classes, without the need of an object of each class.
Does anyone know if it is possible?
Thanks!
In case Your compiler does not support C++17:
template <typename ...ts>
void f() {
for ( const auto &j : { ts::i... } )
i += j;
}
In C++17, your class would simply be
class a {
public:
a() : i(2) {}
template <typename ...ts>
void exec() {
((i += ts::i), ...); // Folding expression // C++17
std::cout << "a::()" << std::endl;
}
int i;
};
Possible in C++11 too, but more verbose.
Reasons why your code is not compiling:
Syntax of specializing templates is a little different.
You need to put the most general case first.
You can't partially specialize functions, only classes.
Partial specialization is not allowed within classes, only in namespaces.
Here is an example for C++11.
#include <iostream>
template<typename t, typename ...ts>
class a {
public:
static constexpr int x = t::i + a<ts...>::x;
};
template<typename t>
class a<t> {
public:
static constexpr int x = 2 + t::i;
};
struct b {
static constexpr int i = -9;
};
struct c {
static constexpr int i = 4;
};
int main()
{
constexpr int result = a<b,c>::x;
std::cout << result << std::endl;
}
Remember that templates are calculated during compilation so, for optimization sake, it is a good idea to write them in a way that allows them to be constexpr.

float or double in templated code

The following example might seem nonsensical, but it's part of a larger high-performance code where the presented technique makes sense. I mention this just in case someone should suspect an XY question - it's most probably not.
I have a function with templated/compile-time operand:
template <int M>
int mul(int x){
return M * x;
}
Now I want to do the same for double, what is - of course - not allowed:
template <double M> // you can't do that!
int mul(double x){
return M * x;
}
So to still put in the double at compile time, I only see the following solution:
// create my constants
struct SevenPointFive{
static constexpr double VAL = 7.5;
}
struct ThreePointOne{
static constexpr double VAL = 3.1;
}
// modified function
template <class M>
int mul(double x){
return M::VAL * x;
}
// call it
double a = mul<SevenPointFive>(3.2);
double b = mul<ThreePointOne>(a);
Is there a better solution for the problem to somehow pass a double constant in a template parameter, without creating a struct for each value?
(I'm interested in a solution which actually uses double/float, not a hack with using two ints to create a rational number or fixed point ideas such as y = 0.01 * M * x.)
In C++11, it is not necessary to use templates at all. Simply use constexpr (generalised constant expressions) in a different way than you are.
#include <iostream>
constexpr double mul(double x, double y)
{
return x*y;
}
int main()
{
std::cout << mul(2.3, 3.4) << '\n';
double x;
std::cin >> x; // to demonstrate constexpr works with variables
std::cout << mul(2.3, x) << '\n';
}
Although I say templates aren't necessary (which they aren't in the example given) these can be templated if needed
template <class T> constexpr T mul(T x, T y) {return x*y;}
or (if you want to use the function for types that are better passed by const reference)
template <class T> constexpr T mul(const T &x, const T &y) {return x*y;}
You can conveniently pass floating point values in template parameters using user-defined literals.
Just write a literal that creates your envelope class. Then you can write something like
mul<decltype(3.7_c)>(7)
Or even better, have your function take the argument by value so you can write
mul(3.7_c, 7)
the compiler will make that just as efficient.
Below's an example of code that does this:
#include <iostream>
template <int Value, char...>
struct ParseNumeratorImpl {
static constexpr int value = Value;
};
template <int Value, char First, char... Rest>
struct ParseNumeratorImpl<Value, First, Rest...> {
static constexpr int value =
(First == '.')
? ParseNumeratorImpl<Value, Rest...>::value
: ParseNumeratorImpl<10 * Value + (First - '0'), Rest...>::value;
};
template <char... Chars>
struct ParseNumerator {
static constexpr int value = ParseNumeratorImpl<0, Chars...>::value;
};
template <int Value, bool, char...>
struct ParseDenominatorImpl {
static constexpr int value = Value;
};
template <int Value, bool RightOfDecimalPoint, char First, char... Rest>
struct ParseDenominatorImpl<Value, RightOfDecimalPoint, First, Rest...> {
static constexpr int value =
(First == '.' && sizeof...(Rest) > 0)
? ParseDenominatorImpl<1, true, Rest...>::value
: RightOfDecimalPoint
? ParseDenominatorImpl<Value * 10, true, Rest...>::value
: ParseDenominatorImpl<1, false, Rest...>::value;
};
template <char... Chars>
using ParseDenominator = ParseDenominatorImpl<1, false, Chars...>;
template <int Num, int Denom>
struct FloatingPointNumber {
static constexpr float float_value =
static_cast<float>(Num) / static_cast<float>(Denom);
static constexpr double double_value =
static_cast<double>(Num) / static_cast<double>(Denom);
constexpr operator double() { return double_value; }
};
template <int Num, int Denom>
FloatingPointNumber<-Num, Denom> operator-(FloatingPointNumber<Num, Denom>) {
return {};
}
template <char... Chars>
constexpr auto operator"" _c() {
return FloatingPointNumber<ParseNumerator<Chars...>::value,
ParseDenominator<Chars...>::value>{};
}
template <class Val>
int mul(double x) {
return Val::double_value * x;
}
template <class Val>
int mul(Val v, double x) {
return v * x;
}
int main() {
std::cout << mul<decltype(3.79_c)>(77) << "\n";
std::cout << mul(3.79_c, 77) << "\n";
return 0;
}
constexpr double make_double( int64_t v, int64_t man );
write a function that makes a double from a base and mantissa. This can represent every non-special double.
Then write:
template<int64_t v, int64_t man>
struct double_constant;
using the above make_double and various constexpr access methods.
You can even write base and exponent extracting constexpr functions I suspect. Add a macro to remove DRY, or use a variable.
Another approach is:
const double pi=3.14;//...
template<double const* v>
struct dval{
operator double()const{return *v;}
};
template<class X>
double mul(double d){
return d*X{};
}
double(*f)(double)=mul<dval<&pi>>;
which requires a variable to point to, but is less obtuse.
If you don't want to create type envelopes for each double/float constant used, then you can create a mapping between integer and double constants. Such mapping can be implemented e.g. as follows:
#include <string>
#include <sstream>
template<int index> double getValue()
{
std::stringstream ss("Not implemented for index ");
ss << index;
throw std::exception(ss.str());
}
template<> double getValue<0>() { return 3.6; }
template<> double getValue<1>() { return 7.77; }
template<int index> double multiply(double x)
{
return getValue<index>() * x;
}
Alternative options to implement the mapping are via a function which does switch-case on the input integer parameter and returns a float/double, or indexing to an array of constants, but both these alternatives would require constexpr for them to happen on compile-time, while some compilers still do not support constexpr: constexpr not compiling in VC2013

C++ (Somehow) limit struct to parent union size

I'm attempting to create a color class of variable size- given a template-determined array of values, I'd like to create named aliases of each value in the array, ie:
template<int C = 3, typename T = unsigned char>
class Color {
public:
union {
T v[C];
struct {
T r, g, b, a;
};
};
};
However, if I try to use the same class for C=3, the union mandates a size of 4 bytes (the 'a' member). Alternatively, using a mathematically expressed bitfield size for a (struct named a, anonymous T member, size evaluates to 1 at C>3), the compiler issues a permissive warning (non-suppressible, as per In gcc, how to mute the -fpermissive warning? ), something unsuitable for a larger-scale API.
How would I go about allowing a single class to handle different numbers of variables, while retaining per-variable names and without implementing recursive-include macro magic (tried this, shouldn't have). Thanks in advance!
Edit: To clarify the question, an answer to any of the following will solve this problem:
Suppress GCC's -fpermissive errors (#pragma diagnostic ignored doesn't work for permissive)
Set maximum size of union or child struct not to exceed C bytes
Allow bitfield length of 0 for members not covered by C bytes (GCC allows mathematical expressions for bitfield length, such as (C-3 > 0)?8:0; )
Disable members not covered by C bytes by some other means (ie, mythical static_if() )
You could make a specialization of the struct for different cases of C:
template <int C = 3, typename T = unsigned char> union Color;
template <typename T>
union Color<3,T> {
T v[3];
struct {
T r,g,b;
};
};
template <typename T>
union Color<4,T> {
T v[4];
struct {
T r,g,b,a;
};
};
Note that anonymous structs are non-standard.
If using member functions is a possibility, I think that would be a better way to go:
template <int C,typename T>
class Color {
public:
using Values = T[C];
Values &v() { return v_; }
const Values &v() const { return v_; }
T& r() { return v_[0]; }
T& g() { return v_[1]; }
T& b() { return v_[2]; }
template <int C2 = C,
typename = typename std::enable_if<(C2>3)>::type>
T& a()
{
return v_[3];
}
const T& r() const { return v_[0]; }
const T& g() const { return v_[1]; }
const T& b() const { return v_[2]; }
template <int C2 = C,
typename = typename std::enable_if<(C2>3)>::type>
const T& a() const
{
return v_[3];
}
private:
Values v_;
};
You can then use it like this:
int main()
{
Color<3,int> c3;
Color<4,int> c4;
c3.v()[0] = 1;
c3.v()[1] = 2;
c3.v()[2] = 3;
std::cout <<
c3.r() << "," <<
c3.g() <<"," <<
c3.b() << "\n";
c4.v()[0] = 1;
c4.v()[1] = 2;
c4.v()[2] = 3;
c4.v()[3] = 4;
std::cout <<
c4.r() << "," <<
c4.g() << "," <<
c4.b() << "," <<
c4.a() << "\n";
}
Okay, so now #VaughnCato had this one out before me, but I'll still post my answer using std::enable_if. It declares Color as struct, because there is really no point in having a class when everything is public (and there is no good reason to declare the data member [v in the question] private), adds template aliases for a bit more syntactic sugar and uses static_assert to make sure the user doesn't use weird values for the template parameters. It also uses std::enable_if in a slightly different manner, which I would argue is a bit more readable.
#include <type_traits>
#include <cstdint>
template<unsigned nChans, typename T = std::uint8_t>
struct Color
{
static_assert(nChans >= 3 || nChans <= 4, "number of color channels can only be 3 or 4");
// allow integral types only
//static_assert(std::is_integral<T>::value, "T has to be an integral type");
// also allow floating-point types
static_assert(std::is_arithmetic<T>::value, "T has to be an arithmetic (integral or floating-point) type");
T data[nChans];
T& r() { return data[0]; }
T& g() { return data[1]; }
T& b() { return data[2]; }
//template<typename U = T, typename EnableIfT = std::enable_if<(nChans == 4), U>::type> // C++11
template<typename U = T, typename EnableIfT = std::enable_if_t<(nChans == 4), U>> // C++14
T& a() { return data[3]; }
const T& r() const { return data[0]; }
const T& g() const { return data[1]; }
const T& b() const { return data[2]; }
//template<typename U = T, typename EnableIfT = std::enable_if<(nChans == 4), U>::type>
template<typename U = T, typename EnableIfT = std::enable_if_t<(nChans == 4), U>>
T const& a() const { return data[3]; }
};
template<typename T = std::uint8_t> using RgbColor = Color<3, T>;
template<typename T = std::uint8_t> using RgbaColor = Color<4, T>;