Selecting a method using different enable_if conditions - c++

I want to write a generic validate function. So i tried writing a meta program.
But it does not gets compiled, and rightly so. Can anyone tell me a way to achieve it.
I am posting my sample code. There can be 3 or more types of structs (here A, B, C), some having a particular type of header, another having other type of header and some even not having a header. So i want to write a program which correctly choose the required function (here f1(), f2() to validate a struct header. I don't want to use Boost Hana or any other reflection library.
#include <iostream>
using namespace std;
struct Header
{
int i;
};
struct OrderHeader
{
int i; int j;
};
struct A
{
Header header;
int val;
};
struct B
{
OrderHeader order_header;
int val;
int c;
};
struct C
{
int val;
int c;
};
bool f1(Header h)
{
return h.i == 1 ? true : false;
}
bool f2(OrderHeader oh)
{
return (oh.i == 1 and oh.j == 1) ? true : false;
}
template<typename St, typename = enable_if_t<is_same_v<decltype(St::header), Header>>>
using v1 = bool;
template<typename St, typename = enable_if_t<is_same_v<decltype(St::order_header), OrderHeader>>>
using v2 = bool;
template<typename St>
bool validate(St s)
{
if constexpr(is_same_v<v1<St>, bool>)
{
return f1(s.header);
}
else if constexpr(is_same_v<v2<St>, bool>)
{
return f2(s.order_header);
}
return true;
}
int main(int argc, char** argv)
{
A at{1,1};
A af{};
C c{};
B b{};
cout << boolalpha << validate(at) << endl;
cout << boolalpha << validate(af) << endl;
cout << boolalpha << validate(b) << endl;
cout << boolalpha << validate(c) << endl;
return 0;
}

if constexpr can be a means for partial compilation, but the condition inside if must always be compilable. In your case v1<St> and v2<St> only exist when St is of the right type, hence the errors.
You can use specialization of variable templates instead, e.g. like this
template<typename, typename = void>
constexpr bool is_v1 = false;
template<typename St>
constexpr bool is_v1<St, enable_if_t<is_same_v<decltype(St::header), Header>>> = true;
template<typename, typename = void>
constexpr bool is_v2 = false;
template<typename St>
constexpr bool is_v2<St, enable_if_t<is_same_v<decltype(St::order_header), OrderHeader>>> = true;
template<typename St>
bool validate(St s)
{
if constexpr (is_v1<St>)
{
return f1(s.header);
}
else if constexpr (is_v2<St>)
{
return f2(s.order_header);
}
return true;
}
Now is_v1<St> and is_v2<St> always return some value (either true or false), and the code should compile1.
1 There's also a typo in f2(): oh.i == 1 and oh.j == 1 should be oh.i == 1 && oh.j == 1.
Also note h.i == 1 ? true : false is tautologous, just h.i == 1 is enough.

Related

Function specialization to access struct members with getter using enum

I have an enum and a struct
enum STORE_ENUM { A_DATA, B_DATA, C_DATA, D_DATA };
struct Store {
int a;
char b;
long c;
bool d;
}
and I want to access its members with a specialized get function that basically looks like this
T get(STORE_ENUM,store s);
and it returns the appropriate type and hopefully statically type checks.
is this possible in C++?
Yes it's possible. The boost PFR library allows something very similar to how you've envisaged it, e.g.:
auto& x = boost::pfr::get<B_DATA>(s);
See the tutorial here.
With C++17, you can do the following
#include <iostream>
enum struct STORE_ENUM { A_DATA, B_DATA, C_DATA, D_DATA };
struct Store {
int a;
char b;
long c;
bool d;
};
template<STORE_ENUM storeEnum>
auto get(Store const & s){
if constexpr (storeEnum == STORE_ENUM::A_DATA) return s.a;
if constexpr (storeEnum == STORE_ENUM::B_DATA) return s.b;
if constexpr (storeEnum == STORE_ENUM::C_DATA) return s.c;
if constexpr (storeEnum == STORE_ENUM::D_DATA) return s.d;
}
int main(){
auto store = Store{ 0, 'a', 4l, true};
std::cout << get<STORE_ENUM::A_DATA>( store) << "\n";
std::cout << get<STORE_ENUM::B_DATA>( store) << "\n";
std::cout << get<STORE_ENUM::C_DATA>( store) << "\n";
std::cout << get<STORE_ENUM::D_DATA>( store) << "\n";
}
See https://godbolt.org/z/1vffh3
In my solution, we don't need enums. It uses templates.
#include <iostream>
#include <type_traits>
struct Store
{
int a;
char b;
long c;
bool d;
Store() //Default constructor
{
a = 0;
b = 0;
c = 0;
d = false;
}
Store(int a, char b, long c, bool d) //Constructor. Custom values.
{
this->a = a;
this->b = b;
this->c = c;
this->d = d;
}
template <typename T = int,
typename = typename std::enable_if<std::is_same<T, int>::value ||
std::is_same<T, char>::value ||
std::is_same<T, long>::value ||
std::is_same<T, bool>::value,
void>::type>
T GetData()
{
if (std::is_same<T, char>::value)
{
return b;
}
if (std::is_same<T, long>::value)
{
return c;
}
if (std::is_same<T, bool>::value)
{
return d;
}
return a;
}
};
int main()
{
Store store { 63, '#', 65, true };
std::cout << store.GetData() << std::endl;
std::cout << store.GetData<>() << std::endl;
std::cout << store.GetData<int>() << std::endl;
std::cout << store.GetData<char>() << std::endl;
std::cout << store.GetData<long>() << std::endl;
std::cout << std::boolalpha << store.GetData<bool>() << std::endl;
}
Output
63
63
63
#
65
true
Compile
clang++ ./main.cpp -std=c++11 or g++ ./main.cpp -std=c++11
Check/run this code in https://repl.it/#JomaCorpFX/FunctionSpecialization#main.cpp
std::tuple basically does this, and your type is basically a tuple. So the easy and fast way is to just reuse std::tuple's machinery.
In c++14 it might look like this:
template<STORE_ENUM e>
auto get( Store s ){
return std::get<(unsigned)e>(std::make_tuple(s.a,s.b,s.c,s.d));
}
template<STORE_ENUM e, class T>
void set( Store& s, T t ){
std::get<(unsigned)e>(std::tie(s.a,s.b,s.c,s.d))=t;
}
This is c++14, but the missing bit for c++11 is easy:
template<STORE_ENUM e>
using store_type = typename std::tuple_element<(unsigned)e, std::tuple<int,char,long,bool>>::type;
template<STORE_ENUM e>
store_type<e> get( Store s ) {
return std::get<(unsigned)e>(std::make_tuple(s.a,s.b,s.c,s.d));
}
template<STORE_ENUM e>
void set( Store& s, store_type<e> v ){
std::get<(unsigned)e>(std::tie(s.a,s.b,s.c,s.d))=v;
}

Not having to list all possibilities with bools and template parameters

(See edit at the end for clarification)
I'm trying to use bool's as template parameters. I'd like to be able to write something like this
#include <iostream>
#include <string>
template<bool a, bool b>
void foo() {
printf("%d %d\n", (int)a, (int)b);
}
int main()
{
int c = 2 ;
c += 2 % 4 - 3 + 1 ;
bool a = c % 2 == 0 ;
bool b = c % 2 == 1 ;
foo<a, b>();
}
but, as expected, I have a
16:9: error: the value of 'a' is not usable in a constant expression
14:10: note: 'bool a' is not const
Of course I could do something like
#include <iostream>
#include <string>
template<bool a, bool b>
void foo() {
printf("%d %d\n", (int)a, (int)b);
}
int main()
{
int c = 2 ;
c += 2 % 4 - 3 + 1 ;
bool a = c % 2 == 0 ;
bool b = c % 2 == 1 ;
if(a) {
if(b) {
foo<true,true>();
} else {
foo<true,false>();
}
} else {
if(b) {
foo<false,true>();
} else {
foo<false,false>();
}
}
}
but it's a bit nasty. Since a and b are bools, is there any way to not have to explicitly list all possibilities ? Could the compiler figure that out by himself ?
EDIT: to clarify: I understand templates are compile time "variables". My question is wether the compiler could automatically generate all the functions, based on the fact that a bool is either true/false (so it's a limite "range" of values, which is what you need to use templates in some sense), and then add the required "plumbing" so that the right function is choosen at runtime.
Thanks,
Template arguments are evaluated at compile time. Now consider this modification of your example:
#include <iostream>
#include <string>
template<bool a, bool b>
void foo() {
printf("%d %d\n", (int)a, (int)b);
}
int main()
{
int c = 2 ;
std::cin >> c;
bool a = c % 2 == 0 ;
bool b = c % 2 == 1 ;
foo<a, b>();
}
Here, there is no way how to evaluate at compile time. Unfortunatelly the compiler cannot distinguish between these two examples.
Compiler cannot generate all the functions itself (if you had ints, would you want it to generate 2**32-1 functions?) unless you ask for specific ones:
#include <iostream>
#include <map>
#include <functional>
template <bool a, bool b>
void func() {
std::cout << std::boolalpha << a << " " << std::boolalpha << b << std::endl;
}
std::map<bool, std::map<bool, std::function<void ()>>> dispatcher;
template <bool a, bool b>
void register_dispatcher() {
dispatcher[a][b] = func<a,b>;
}
int main() {
register_dispatcher<false, false>();
register_dispatcher<false, true>();
register_dispatcher<true, false>();
register_dispatcher<true, true>();
bool a, b;
a = false;
b = true;
dispatcher[a][b]();
// for clarity I don't handle nonexistent keys
return 0;
}
Note that the code requires C++11.
Now you may want 10 bool arguments and generate each of them. Beware, that's 1024 functions. Not that much, but be careful. Let's do it with 3:
#include <iostream>
#include <map>
#include <functional>
template <bool a, bool b, bool c>
void func() {
std::cout
<< std::boolalpha << a << " "
<< std::boolalpha << b << " "
<< std::boolalpha << c << " "
<< std::endl;
}
std::map<bool, std::map<bool, std::map<bool, std::function<void ()>>>> dispatcher;
template <bool a, bool b, bool c>
void register_dispatcher() {
dispatcher[a][b][c] = func<a,b, c>;
}
template <bool a, bool b>
void register_dispatcher_2() {
register_dispatcher<a, b, true>();
register_dispatcher<a, b, false>();
}
template <bool a>
void register_dispatcher_1() {
register_dispatcher_2<a, true>();
register_dispatcher_2<a, false>();
}
void register_dispatcher_0() {
register_dispatcher_1<true>();
register_dispatcher_1<false>();
}
int main() {
register_dispatcher_0();
bool a, b, c;
a = false;
b = true;
c = true;
dispatcher[a][b][c]();
return 0;
}
The code generates one argument at a time. It would start being worth it at some 7 or 8 arguments, or when you start mixing in ints.
By adding some const/constexpr, you may do
constexpr int c_ini = 2 ;
constexpr int c = c_ini + 2 % 4 - 3 + 1 ;
constexpr bool a = c % 2 == 0 ;
constexpr bool b = c % 2 == 1 ;
foo<a, b>();
Demo

breakpoint in template for specific template parameter

What if i want to set breakpoint into constructor with condition if I == 10?
template < typename T, int I >
class C
{
public:
C<T, I>() { cout << I << endl; }
};
If conditional break point does not work try
template < typename T, int I >
class C
{
public:
C()
{
if(I == 10)
{
* int a= 0; //or try __debugbreak();
}
cout << I << endl;
}
};
EDIT
To break on specific class you may use std::is_same<T, U>::value(or boost analogue) in condition

Using template to generate a static lookup table

I have:
const char kLetters[] = "QWERTYUIOPASDFGHJKLZXCVBNM";
I can call kLetters[n] to obtain the nth letter of the Keyboard alphabet in O(1) time. However I will have to iterate through kLetter (taking O(n) or at least O(log n) ) time for the reverse lookup.
I would like to create a reverse lookup table as a compile-time static lookup table using templates and was wondering if there is a ways of doing this.
EDIT - as mentioned in the comments, a reverse lookup would mean I supply 'E' and get back 2. Also my alphabet example was not the best example, I would like to make no assumptions about the order. For that reason I have change the alphabet to keyboard order.
How about something like this? It lets you specify the range rather than a complete string.
#include <iostream>
template <int Start, int End, int N>
struct lookup {
static_assert(Start != End, "Can't have 0 length lookup table");
enum { value = lookup<Start+(Start < End ? 1:-1),End,N-1>::value };
};
template <int Start, int End>
struct lookup<Start,End,0> {
enum { value = Start };
};
template <int Start, int End, int V, int P=0>
struct reverse_lookup {
static_assert(Start != End, "V isn't in the range Start, End");
static_assert(Start != End || !P, "Can't have 0 length range");
enum { value = reverse_lookup<Start+(Start < End ? 1:-1),End,V,P+1>::value };
};
template <int Start, int End, int P>
struct reverse_lookup<Start,End,Start,P> {
enum { value = P };
};
int main() {
std::cout << char(lookup<'A', 'Z', 3>::value) << std::endl;
std::cout << char(lookup<'Z', 'A', 3>::value) << std::endl;
std::cout << int(reverse_lookup<'A','Z','F'>::value) << std::endl;
}
Alright, after knowing what reverse lookup is, I think you can do this:
const char kLetters[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
int get_index(char letter)
{
return letter - 'A';
}
After all, the letter A is at index 0, B at 1, C at 2... and so on. That gives enough hint.
My O(1) solution.
So far other solutions work for non-arbitrary sequence of letters, and #awoodland solution assumes that the letter whose index is to be obtainted is known at compile time which makes it less useful.
But this solution has attempted to solve both limitations; that is, it should work:
With arbitrary sequence of letters, such as
const char Letters[] = "ZBADCEWFVGHIUXJTKSLYQMROPN";
And the letters may be unknown at compile time. The function that gets the index has this signature:
int Index(char letter);
Here is the complete code which uses a technique described by # David Rodríguez in his blog:
#include <iostream>
const char Letters[] = "ZBADCEWFVGHIUXJTKSLYQMROPN";
template<char L> int Index();
template<> int Index<'Z'>() { return 0; }
template<> int Index<'B'>() { return 1; }
template<> int Index<'A'>() { return 2; }
template<> int Index<'D'>() { return 3; }
template<> int Index<'C'>() { return 4; }
template<> int Index<'E'>() { return 5; }
template<> int Index<'W'>() { return 6; }
template<> int Index<'F'>() { return 7; }
template<> int Index<'V'>() { return 8; }
template<> int Index<'G'>() { return 9; }
template<> int Index<'H'>() { return 10; }
template<> int Index<'I'>() { return 11; }
template<> int Index<'U'>() { return 12; }
template<> int Index<'X'>() { return 13; }
template<> int Index<'J'>() { return 14; }
template<> int Index<'T'>() { return 15; }
template<> int Index<'K'>() { return 16; }
template<> int Index<'S'>() { return 17; }
template<> int Index<'L'>() { return 18; }
template<> int Index<'Y'>() { return 19; }
template<> int Index<'Q'>() { return 20; }
template<> int Index<'M'>() { return 21; }
template<> int Index<'R'>() { return 22; }
template<> int Index<'O'>() { return 23; }
template<> int Index<'P'>() { return 24; }
template<> int Index<'N'>() { return 25; }
typedef int (*fptr)();
const int limit = 26;
fptr indexLookup[ limit ];
template <char L>
struct init_indexLookup {
static void init( fptr *indexLookup ) {
indexLookup[ L - 'A' ] = &Index<L>;
init_indexLookup<L-1>::init( indexLookup );
}
};
template <>
struct init_indexLookup<'A'> {
static void init( fptr *indexLookup ) {
indexLookup[ 0 ] = &Index<'A'>;
}
};
const int ignore = (init_indexLookup<'Z'>::init(indexLookup),0);
int Index(char letter)
{
return indexLookup[letter-'A']();
}
And here is the test code:
int main()
{
std::cout << Index('A') << std::endl;
std::cout << Index('Z') << std::endl;
std::cout << Index('B') << std::endl;
std::cout << Index('K') << std::endl;
}
Output:
2
0
1
16
Online demo : http://ideone.com/uzE2t
Well, that actually is two function calls: one to Index(), other to from one in the indexLookup. You can easily avoid first function call by writing (ideone):
int main()
{
std::cout << indexLookup['A'-'A']() << std::endl;
std::cout << indexLookup['Z'-'A']() << std::endl;
std::cout << indexLookup['B'-'A']() << std::endl;
std::cout << indexLookup['K'-'A']() << std::endl;
}
That looks cumbersome, but hey, we can make Index() inline:
inline int Index(char letter)
{
return indexLookup[letter-'A']();
}
That looks fine, and most likely now compiler will make it equivalent to one function call!
Simple yet O(1) solution
Wait. I just realized that the whole solution reduces to a lookup table which is initialized as:
const int indexLookup[] = {2,1,4,3,5,7,9,10,11,14,16,18,21,
25,23,24,20,22,17,15,12,8,6,13,19,0};
inline int Index(char letter)
{
return indexLookup[letter-'A'];
}
which looks unbelievably simple!
If you can use Boost and only need compile-time lookups:
using namespace boost::mpl;
typedef vector_c<char, 'A', 'B', 'C', 'D'> Chars;
// lookup by index:
std::cout << at_c<Chars, 1>::type::value << std::endl; // B
// lookup by value:
typedef find<Chars, integral_c<char, 'C'> >::type Iter;
std::cout << Iter::pos::value << std::endl; // 2
This assumes that 'Z' > 'A', but does not assume letters are contiguous. (Though it takes less memory if they are) I was tempted to put in if (numrLetters>26) conditionals so a smart compiler could use addition rather than the tables for ASCII, but then decided I didn't want to slow the code in the case of less-smart compilers.
const char kLetters[] = "ABCDEFGHJJKLMNOPQRSTUVWXYZ";
const int numLetters = sizeof(kLetters);
const char rkLetters['Z'-'A'] = {};
const int numrLetters = sizeof(rkLetters);
struct LetterInit {
LetterInit() {
for(int i=0; i<numLetters; ++i)
rkLetters[kLetters[i]-'A'] = i;
}
}LetterInitInst;
char findChar(int index) {
assert(index>=0 && index<numLetters);
return kLetters[index];
}
int findIndex(char letter) {
assert(letter>='A' && letter<='Z');
return rkLetters[letter-'A'];
}
As there are several solutions given that don't generate a table but still allow compile time lookup, here is another one
constexpr char kLetters[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
constexpr int get(char const x, int const i = 0) {
return kLetters[i] == x ? i : get(x, i + 1);
}
Use at compile time
int x[get('F')];
static_assert(sizeof(x) == sizeof(int[5]), "");
Specifying a character that doesn't exist will result in an error. If you use the function at runtime, you will get undefined behavior if you specify a character that doesn't exist. Proper checking can be added for those cases.
It yields the index of the first character found. No error is given if a character appears twice in the haystack.
If you can use c++0x (tested with gcc 4.5), this works:
#include<initializer_list>
#include<iostream>
#include<map>
constexpr int getLetterNumber(char a){ return std::map<char,int>({{'a',2},{'b',1},{'c',4}})[a]; }
int main(){
const char ch='b';
std::cout<<ch<<": "<<getLetterNumber(ch)<<std::endl;
}
constexpr enforces evaluation at compile-time.
EDIT: that solution is not correct, as pointed out. constexpr does not enfoce compile-time evaluation. This does does the lookup really at compile-time (similar to solutions posted meanwhile).
#include<iostream>
template<char C> int ch2Num();
#define CHR(c,i) template<> int ch2Num<c>(){ return i; }
CHR('a',2); CHR('b',1); /* ... */
#undef CHR
int main(void){
const char ch='b';
std::cout<<ch<<": "<<ch2Num<ch>()<<std::endl;
};

Elegant template specialization

Is there an elegant way to specialize a template based on one of its template parameters?
Ie.
template<int N> struct Junk {
static int foo() {
// stuff
return Junk<N - 1>::foo();
}
};
// compile error: template argument '(size * 5)' involves template parameter(s)
template<int N> struct Junk<N*5> {
static int foo() {
// stuff
return N;
}
};
template<> struct Junk<0> {
static int foo() {
// stuff
return 0;
}
};
Ie. I am trying to specialize a template based on the parameter being divisible by 5. The only way I can seem to do it is like below:
template<int N> struct JunkDivisibleBy5 {
static int foo() {
// stuff
return N;
}
};
template<int N> struct Junk {
static int foo() {
// stuff
if ((N - 1) % 5 == 0 && N != 1)
return JunkDivisibleBy5<N - 1>::foo();
else
return Junk<N - 1>::foo();
}
};
template<> struct Junk<0> {
static int foo() {
// stuff
return 0;
}
};
But this is significantly less elegant, and also necessitates instantiation of all templates even if the template argument shouldn't require it.
How's this:
#include <iostream>
using namespace std;
template < typename T, T N, T D >
struct fraction {
typedef T value_type;
static const value_type num = N;
static const value_type denom = D;
static const bool is_div = (num % denom == 0);
};
template< typename T, T N, T D, bool P >
struct do_if {
static void op() { cout << N << " NOT divisible by " << D << endl; }
};
template< typename T, T N, T D >
struct do_if< T, N, D, true > {
static void op() { cout << N << " divisible by " << D << endl; }
};
template < int N >
void foo() {
typedef fraction< int, N, 5 > f;
do_if< typename f::value_type, f::num, f::denom, f::is_div >::op();
}
int main() {
foo< -5 >();
foo< -1 >();
foo< 0 >();
foo< 1 >();
foo< 5 >();
foo< 10000005 >();
return 0;
}
Using D programming language templates, one could write it as:
struct Junk(int N)
{
static int foo()
{
static if (N == 0)
return 0;
else static if ((N % 5) == 0)
return N;
else
return Junk!(N - 1).foo();
}
}
static if's are executed at compile time.
All calculations could be made in compile-time:
#include <iostream>
template<int N> struct Junk {
enum { IsDivisibleBy5 = (N % 5 == 0) };
template<bool D> struct JunkInternal {
enum { Result = Junk<N-1>::Result };
};
template<> struct JunkInternal<true> {
enum { Result = N };
};
enum { Result = JunkInternal<IsDivisibleBy5>::Result };
};
int main(int, char**)
{
std::cout << Junk< 0 >::Result << std::endl;
std::cout << Junk< 7 >::Result << std::endl;
std::cout << Junk< 10 >::Result << std::endl;
return 0;
}
Code
template<int A, bool = !(A % 5)>
struct select : select<A-1> { };
template<int A>
struct select<A, true> { static int const value = A; };
template<>
struct select<0, true> { static int const value = 0; };
int main() {
std::cout << select<1>::value; // 0
std::cout << select<7>::value; // 5
std::cout << select<10>::value; // 10
}
Keep the divisor variable
template<int A, int D, bool = !(A % D)>
struct select : select<A-1, D> { };
template<int A, int D>
struct select<A, D, true> { static int const value = A; };
template<int D>
struct select<0, D, true> { static int const value = 0; };
int main() {
std::cout << select<1, 3>::value; // 0
std::cout << select<7, 3>::value; // 6
std::cout << select<10, 3>::value; // 9
}
Inheritance works quite well:
template<int N> struct Junk : private JunkBase < N % 5 > { };
template<int N> struct JunkBase {
static int foo() {
// stuff
return Junk<N - 1>::foo();
}
};
template< > struct JunkBase<0> {
static int foo() {
return 0;
}
};
You might need to pass N to JunkBase::foo, if you need N/5 too.
I would hardly call it elegant, but here's my version of your code using only templates for computation (along with a test thing) --
#include <iostream>
template < int N > struct JunkDivBy5 {
static int foo() {
return N;
}
};
template < int N > struct Junk {
template < int N1 > struct _JunkCond {
enum { val = ( N1 != 1 && ( N1 - 1 ) % 5 == 0 ) ? 1 : 0 };
};
template < int M, int N1 > struct _JunkBranch { /* Error */ };
template < int N1 > struct _JunkBranch< 1, N1 > {
typedef JunkDivBy5< N1 - 1 > Type;
};
template < int N1 > struct _JunkBranch< 0, N1 > {
typedef Junk< N1 - 1 > Type;
};
static int foo() {
return _JunkBranch< _JunkCond< N >::val, N >::Type::foo();
}
};
template <> struct Junk< 0 > {
static int foo() {
return 0;
}
};
int main( int argc, char *argv[] ) {
std::cout << Junk< 0 >::foo() << std::endl;
std::cout << Junk< 5 >::foo() << std::endl;
std::cout << Junk< 7 >::foo() << std::endl;
std::cout << Junk< 25 >::foo() << std::endl;
}