Related
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;
}
Having fun with boost::hana. I wish to check for a specific nested type that acts like a tag in another type, so I borrow from hana::when_valid example and defined a class is_S along with its SFINAE-enabled specialization:
#include <iostream>
#include <boost/hana/core/when.hpp>
namespace hana = boost::hana;
#define V(x) std::cout << x << std::endl
struct S_tag { };
struct S {
using tag = S_tag;
};
struct T {
using tag = int;
};
template< typename T, typename = hana::when< true > >
struct is_S {
static constexpr bool value = false;
};
template< typename T >
struct is_S< T, hana::when_valid< typename T::tag > > {
static constexpr bool value = std::is_same<
typename T::tag, S_tag >::value;
};
int main () {
std::cout << "is_S ( S { }) = "; V ((is_S< S >::value));
std::cout << "is_S ( T { }) = "; V ((is_S< T >::value));
std::cout << "is_S (float { }) = "; V ((is_S< float >::value));
return 0;
}
This prints:
$ clang++ -std=c++1z sfinae.cpp && ./a.out | c++filt
is_S ( S { }) = 1
is_S ( T { }) = 0
is_S (float { }) = 0
Is there a simpler/shorter/more succinct way of writing the same check, in keeping with value-type computation of hana philosophy?
Here's what I might write:
#include <boost/hana.hpp>
#include <iostream>
namespace hana = boost::hana;
struct S_tag { };
struct S { using tag = S_tag; };
struct T { using tag = int; };
auto tag_of = [](auto t) -> hana::type<typename decltype(t)::type::tag> {
return {};
};
auto is_S = [](auto t) {
return hana::sfinae(tag_of)(t) == hana::just(hana::type<S_tag>{});
};
int main() {
std::cout << "is_S ( S { }) = " << is_S(hana::type<S>{})() << std::endl;
std::cout << "is_S ( T { }) = " << is_S(hana::type<T>{})() << std::endl;
std::cout << "is_S (float { }) = " << is_S(hana::type<float>{})() << std::endl;
}
I woukd be tempted by:
template<class...T>
constexpr std::integral_constant<bool,false> is_S(T const&...){ return {}; }
template<class T>
constexpr
std::integral_constant<bool,std::is_same<typename T::tag,S_tag>{}>
is_S(T const&){ return {}; }
I asked How do I capture the results of a recursive function at compile-time?, but I think my approach was wrong.
I have a program like so:
#include <iostream>
#include <list>
std::list<unsigned int> recursive_case(std::list<unsigned int>& result, unsigned int& i) {
result.push_front(1 + (i % 10));
i /= 10;
return i != 0 ? recursive_case(result, i) : result;
}
std::list<unsigned int> initial_case(unsigned int i) {
std::list<unsigned int> result;
result.push_back(i % 10);
i /= 10;
return i != 0 ? recursive_case(result, i) : result;
}
int main() {
auto list = initial_case(123);
bool first = true;
for (auto i: list) {
if (first) {
first = false;
} else {
std::cout << ", ";
}
std::cout << i;
}
std::cout << std::endl;
}
The output is 2, 3, 3.
I want to perform the above computation and get the same output but in compile-time (the loop iteration and output-printing would be at runtime i.e. everything starting from the for loop). Templates seem like a possibility (that's why I tagged this ask as such), but I am open to anything that gets the job done in compile-time.
You can use constexpr to calculate the list at compile time. I converted the recursion to iteration and used the indices trick to call calculate as often as necessary.
#include <iostream>
#include <array>
#include <iterator>
#include <utility>
constexpr std::size_t count_digits(std::size_t N, std::size_t Count = 0)
{
return (N > 0) ? count_digits(N/10, Count+1) : Count;
}
constexpr std::size_t ipow(std::size_t N, std::size_t Base)
{
return (N > 0) ? Base*ipow(N-1,Base) : 1;
}
constexpr std::size_t calculate(std::size_t n, std::size_t i)
{
std::size_t p = ipow(i,10);
std::size_t t = (n/p) % 10;
return i > 0 ? (t+1) : t;
}
template<std::size_t Num, std::size_t C, std::size_t... Is>
constexpr std::array<std::size_t, C> build_list(std::index_sequence<Is...>)
{
return {{ calculate(Num, C-Is-1)... }};
}
template <std::size_t Num, std::size_t C = count_digits(Num)>
constexpr auto build_list()
{
return build_list<Num, C>(std::make_index_sequence<C>{});
}
int main()
{
constexpr auto list = build_list<123>();
for(auto e : list)
{
std::cout << e << " ";
}
return 0;
}
output:
2 3 3
live example
Here's one solution.
#include <iostream>
// Print one digit.
template <unsigned int N, bool Initial> struct AtomicPrinter
{
static void print()
{
std::cout << N%10;
}
};
template <unsigned int N> struct AtomicPrinter<N, false>
{
static void print()
{
std::cout << 1 + N%10 << ", ";
}
};
// Recursive printer for a number
template <unsigned int N, bool Initial> struct Printer
{
static void print()
{
Printer<N/10, false>::print();
AtomicPrinter<N, Initial>::print();
}
};
// Specialization to end recursion.
template <bool TF> struct Printer<0, TF>
{
static void print()
{
}
};
void printList()
{
Printer<123, true>::print();
std::cout << std::endl;
}
int main() {
printList();
}
If there is a need to separate printing of the digits from constructing the list of digits, you can use:
#include <iostream>
#include <list>
template <unsigned int N, bool Initial> struct Digit
{
static void get(std::list<int>& l)
{
l.push_back(N%10);
}
};
template <unsigned int N> struct Digit<N, false>
{
static void get(std::list<int>& l)
{
l.push_back(1 + N%10);
}
};
template <unsigned int N, bool Initial> struct Digits
{
static void get(std::list<int>& l)
{
Digits<N/10, false>::get(l);
Digit<N, Initial>::get(l);
}
};
template <bool TF> struct Digits<0, TF>
{
static void get(std::list<int>& l)
{
}
};
void printList()
{
std::list<int> l;
Digits<123, true>::get(l);
bool first = true;
for (auto i: l) {
if (first) {
first = false;
} else {
std::cout << ", ";
}
std::cout << i;
}
std::cout << std::endl;
}
int main() {
printList();
}
You may use something like the following to split number at compile time:
#include <utility>
#include <iostream>
template <char... Cs>
std::integer_sequence<char, Cs...> operator "" _seq() { return {}; }
template <char...Cs>
void print(std::integer_sequence<char, Cs...>)
{
const char* sep = "";
for (const auto& c : {Cs...}) {
std::cout << sep << c;
sep = ", ";
}
}
int main() {
auto seq = 123_seq;
print(seq);
}
Demo
I would like to use variadic templates to help solve an issue using va-args. Basically, I want to call a singular function, pass into the function a "command" along with a variable list of arguments, then dispatch the arguments to another function.
I've implemented this using tried and true (but not type safe) va_list. Here's an attempt I made at doing this using variadic templates. The example doesn't compile below as you will quickly find out why...
#include <iostream>
using namespace std;
typedef enum cmd_t
{
CMD_ZERO,
CMD_ONE,
CMD_TWO,
} COMMANDS;
int cmd0(double a, double b, double c)
{
cout << "cmd0 " << a << ", " << b << ", " << c << endl;
return 0;
}
int cmd1(int a, int b, int c)
{
cout << "cmd1 " << a << ", " << b << ", " << c << endl;
return 1;
}
template<typename... Args>
int DispatchCommand(COMMANDS cmd, Args... args)
{
int stat = 0;
switch (cmd)
{
case CMD_ZERO:
cmd0(args...);
break;
case CMD_ONE:
cmd1(args...);
break;
default:
stat = -1;
break;
}
return stat;
}
int main()
{
int stat;
stat = DispatchCommand(CMD_ZERO, 1, 3.141, 4);
stat = DispatchCommand(CMD_ONE, 5, 6, 7);
stat = DispatchCommand(CMD_TWO, 5, 6, 7, 8, 9);
system("pause");
return 0;
}
Does anyone have an idea on how I can modify this function to use variadic templates correctly?
Write some code that, given a function pointer and a set of arguments, calls it with the longest prefix of those arguments that works.
template<class...>struct types{using type=types;};
template<class types0, size_t N, class types1=types<>>
struct split;
template<class t00, class...t0s, size_t N, class...t1s>
struct split<types<t00,t0s...>,N,types<t1s...>>:
split<types<t0s...>,N-1,types<t1s...,t00>>
{};
template<class...t0s, class...t1s>
struct split<types<t0s...>,0,types<t1s...>>
{
using right=types<t0s...>;
using left=types<t1s...>;
};
template<class>using void_t=void;
template<class Sig,class=void>
struct valid_call:std::false_type{};
template<class F, class...Args>
struct valid_call<F(Args...), void_t<
decltype( std::declval<F>()(std::declval<Args>()...) )
>>:std::true_type {};
template<class R, class types>
struct prefix_call;
template<class R, class...Args>
struct prefix_call<R, types<Args...>> {
template<class F, class... Extra>
std::enable_if_t< valid_call<F(Args...)>::value, R >
operator()(R default, F f, Args&&...args, Extra&&...) const
{
return std::forward<F>(f)(args...);
}
template<class F, class... Extra>
std::enable_if_t< !valid_call<F(Args...)>::value, R >
operator()(R default, F f, Args&&...args, Extra&&...) const
{
return prefix_call<R, typename split<types<Args...>, sizeof...(Args)-1>::left>{}(
std::forward<R>(default), std::forward<F>(f), std::forward<Args>(args)...
);
}
};
template<class R>
struct prefix_call<R, types<>> {
template<class F, class... Extra>
std::enable_if_t< valid_call<F()>::value, R >
operator()(R default, F f, Extra&&...) const
{
return std::forward<F>(f)();
}
template<class F, class... Extra>
std::enable_if_t< !valid_call<F()>::value, R >
operator()(R default, F f, Extra&&...) const
{
return std::forward<R>(default);
}
};
the above code may contain typos.
template<typename... Args>
int DispatchCommand(COMMANDS cmd, Args... args)
{
int stat = 0;
switch (cmd) {
case CMD_ZERO: {
stat = prefix_call<int, Args...>{}(-1, cmd0, std::forward<Args>(args)...);
} break;
case CMD_ONE: {
stat = prefix_call<int, Args...>{}(-1, cmd1, std::forward<Args>(args)...);
} break;
default: {
stat = -1;
} break;
}
return stat;
}
If cmd0 or cmd1 is overridden, you'll have to use the overload set technique.
You may use the following:
template <COMMANDS cmd> struct command
{
template <typename ... Args>
int operator() (Args&&...) const { return -1; }
};
template <> struct command<CMD_ZERO>
{
int operator()(double a, double b, double c) const
{
std::cout << "cmd0 " << a << ", " << b << ", " << c << std::endl;
return 0;
}
};
template <> struct command<CMD_ONE>
{
int operator()(int a, int b, int c) const
{
std::cout << "cmd1 " << a << ", " << b << ", " << c << std::endl;
return 1;
}
};
template <COMMANDS cmd, typename... Args> int DispatchCommand(Args&&... args)
{
return command<cmd>()(std::forward<Args>(args)...);
}
And then use it like:
DispatchCommand<CMD_ZERO>(1., 3.141, 4.);
DispatchCommand<CMD_ONE>(5, 6, 7);
DispatchCommand<CMD_TWO>(5, 6, 7, 8, 9);
Live example
But using directly the different functions seems simpler:
cmd0(1., 3.141, 4.);
cmd1(5, 6, 7);
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;
}