How to get value of integer template parameter? - c++

title might be confusing, but lets say I have a template:
template <typename T, size_t offset>
struct offsetedIdxArray
{
//...
}
And after I create an instance:
static const size_t offset(1701);
offsetedIdxArray<zmq::socket_t, offset> oia;
Is there a way to get offset variable from oia. I know I can just use offset but from code style perspective i prefer to get it from oia if possible.
EDIT: I'm looking for a way to get offset without helper variable inside struct...

If you want to obtain the information from an offsetedIdxArray<T,N> object without adding any members to the class template, you can use a template function:
#include <iostream>
#include <cstddef>
template <typename T, size_t offset>
struct offsetedIdxArray
{
};
template <typename T, size_t offset>
size_t getOffset(const offsetedIdxArray<T, offset>&) {
return offset;
}
int main()
{
offsetedIdxArray<int,5> oia;
std::cout << getOffset(oia) << "\n";
}
Otherwise you can add a static constant or enum data member, as suggested in other posts.

template <typename T, size_t offset>
struct offsetedIdxArray
{
static const size_t off = offset;
//...
};
and get the variable off.

Related

Accepting std::array of char of any size as non type template parameter

This is probably a weird use case, but I am trying to hack around the fact string literals can not be used as arguments to templates using std::array<char, N> as non template type parameter.
This works but with extreme limitation that all strings must be of same length(I could use MAX_STR_LEN=100 or whatever and make all arrays that size, but that feels ugly...).
Is there a way to make this code work so that different size std::arrays can be accepted as template parameter?
#include <iostream>
#include <array>
#include <tuple>
#include <boost/mp11/algorithm.hpp>
#include <boost/mp11/tuple.hpp>
// I wish that this 6 is not fixed... but IDK how to fix it, maybe concept(IDK if concepts can be used as "types" on NTTP.
template <typename Type, std::array<char, 6> val_val>
struct TypeToValues
{
using type = Type;
static constexpr const char* val = val_val.data();
};
template <std::size_t Sz, std::size_t... Is>
constexpr std::array<char, Sz>
arrayify(const char (&arr)[Sz], std::index_sequence<Is...>)
{
return {{arr[Is]...}};
}
template <std::size_t Sz>
constexpr std::array<char, Sz> arrayify(const char (&arr)[Sz])
{
return arrayify(arr, std::make_index_sequence<Sz>());
}
struct HelloType{
};
struct YoloType{
};
int main(){
std::tuple<
TypeToValues<HelloType, arrayify("Hello")>,
TypeToValues<YoloType, arrayify("Yolo!")>> mapping;
boost::mp11::tuple_for_each(mapping, []<typename T>(const T&){
if constexpr(std::is_same_v<typename T::type, HelloType>){
std::cout << "HelloType says: " << T::val << std::endl;;
}
if constexpr(std::is_same_v<typename T::type, YoloType>){
std::cout << "YoloType says: " << T::val << std::endl;;
}
});
}
Sure, why not use a requires requires clause?
template <typename Type, auto val_val>
requires requires { { val_val.data() } -> std::same_as<char const*>; }
struct TypeToValues
{
// ...
Example.
You could also write a constraint that only specifically std::array<char, N> satisfy:
template<class> constexpr bool is_array_of_char_v = false;
template<unsigned N> constexpr bool is_array_of_char_v<std::array<char, N>> = true;
template<class T> concept ArrayOfChar = requires { is_array_of_char_v<T>; };
template <typename Type, ArrayOfChar auto val_val>
struct TypeToValues
{
// ...
But that feels excessively restrictive; you'll want to accept static string types in future.

Changing template arguments at runtime c++

I have a large and complex program that makes use of templates quite extensively.
For the sake of simplicity, consider I have the following classes in my program:
BronzeFork , SilverFork, GoldFork
SimpleKnife , SerratedKnife, ButterKnife
RedSpoon , GreenSpoon, BlueSpoon
and then in main.cpp I call a function:
Eating<BronzeFork, SerratedKnife, BlueSpoon>::runEat();
My aim is to be able to be able to feed arguments at runtime to my (compiled) program in order to modify the kind of fork or spoon that I want in this run.
I could do it with a very large switch statement running every combination of forks, knives and spoons but it seems quite messy, convoluted and hard to maintain.
Especially because I am continuously adding kinds of Forks, Knifes and Spoons into the program.
What would be the best way to do this in a clean, efficient way?
This is not necessarily the best way to solve your problem. This is one way to generate a lot of instantiations in a compact manner. It may or may not suit your need.
I assume each of your classes have some kind of ID for run-time selection, say a string. So BronzeFork::id would be "BronzeFork". I will use abbreviated names henceforth.
#include <tuple>
#include <string>
#include <functional>
#include <map>
struct F1 { static constexpr const char* id = "F1"; };
struct F2 { static constexpr const char* id = "F2"; };
struct F3 { static constexpr const char* id = "F3"; };
struct K1 { static constexpr const char* id = "K1"; };
struct K2 { static constexpr const char* id = "K2"; };
struct K3 { static constexpr const char* id = "K3"; };
struct S1 { static constexpr const char* id = "K1"; };
struct S2 { static constexpr const char* id = "K2"; };
struct S3 { static constexpr const char* id = "K3"; };
template <typename F, typename K, typename S> struct Eater
{
static void eat();
};
using t3 = std::tuple<std::string, std::string, std::string>;
std::map<t3, std::function<void()>> funcMap;
Now we need to populate funcMap. We need nested compile-time loops. I implement them as separate templates using fold-expressions. There might be a better way, but this one is very unsophisticated and straightforward so it's easy to understand.
template <typename F, typename K, typename S> struct populate0
{
void operator()() { funcMap.insert({{F::id, K::id, S::id}, Eater<F, K, S>::eat}); }
};
// Inner loop
template <typename Fs, typename K, typename S> struct populate1;
template <typename ... Fs, typename K, typename S>
struct populate1 <std::tuple<Fs...>, K, S> // loop over Fs
{
void operator()() { (populate0<Fs, K, S>()(), ...); }
};
// Middle loop
template <typename Fs, typename Ks, typename S> struct populate2;
template <typename Fs, typename ... Ks, typename S>
struct populate2 <Fs, std::tuple<Ks...>, S> // loop over Ks
{
void operator()() { (populate1<Fs, Ks, S>()(), ...); }
};
// Outer loop
template <typename Fs, typename Ks, typename Ss> struct populate3;
template <typename Fs, typename Ks, typename... Ss> // loop over Ss
struct populate3 <Fs, Ks, std::tuple<Ss...>>
{
void operator()() { (populate2<Fs, Ks, Ss>()(), ...); }
};
Now we need to just run the loop.
populate3<std::tuple<F1, F2, F3>,
std::tuple<K1, K2, K3>,
std::tuple<S1, S2, S3>>()();
Whenever you add another class, add it to this call.
C++ is a compilable language, meaning that the types must be known at code-generation-time. Virtual classes could be a solution to your case.
This is not incompatible with the use of templates, which can keep the source code compact. But all specializations with the types you can meet at run-time must be instantiated.

Infinite recursion in templates

Suppose I have a proxy class called List which is nothing more than a holder for a bunch of typenames:
template<typename... items> class List {
constexpr size_t SizeOf = /*Magic code that determines the length*/;
};
And suppose I have another class which is supposed to take to Lists and output a version where the smaller one is padded with null_ts:
template<class flist,class slist>
class Pad{
typedef /*Undertermined*/ Flist;
typedef /*Undertermined*/ Slist;
};
The only real problem is breaking the recursion....normally in template recursion you just specialize and then you can end it.
Here is a little different because there is no way (at least that I can see) to tell by the template deceleration the difference between the two list.
I tried to use a std::conditional to end the cycle but that does not work.
Here is an example:
template<int x>
class Mine{
typedef std::conditional<x == 12, Mine<x>::value, Mine<x+1>::value> value;
};
Even though I have the x==12 condition it still needs (or wants) to flush out the Mine<x+1>::value.
So what is the general strategy for this scenario?
This is a non-recursive solution for the implementation of Pad, but it also shows how you can use partial specialization to avoid instantiating templates based on a condition:
#include <cstddef>
#include <utility>
#include <type_traits>
#include <iostream>
template<class... Ts> struct List { static constexpr std::size_t size = sizeof...(Ts); };
struct null_t { };
template<std::size_t> using make_null_t = null_t;
template<class, class> struct pad_imp2;
template<class... Ts, std::size_t... Is> struct pad_imp2<List<Ts...>, std::index_sequence<Is...>>
{
using type = List<Ts..., make_null_t<Is>...>;
};
// Don't instantiate make_index_sequence if L::size >= S.
template<class, std::size_t, bool> struct pad_imp { using type = void; };
template<class L, std::size_t S> struct pad_imp<L, S, true>
{
using type = typename pad_imp2<L, std::make_index_sequence<S - L::size>>::type;
};
template<class L, std::size_t S> using pad_hlp = typename pad_imp<L, S, L::size < S>::type;
template<class L1, class L2> struct Pad
{
using L1_padded = std::conditional_t<L1::size < L2::size, pad_hlp<L1, L2::size>, L1>;
using L2_padded = std::conditional_t<L2::size < L1::size, pad_hlp<L2, L1::size>, L2>;
};
int main()
{
using list1 = List<short, int, long>;
using list2 = List<double>;
std::cout << std::is_same<Pad<list1, list2>::L1_padded, list1>::value << '\n';
std::cout << std::is_same<Pad<list1, list2>::L2_padded, List<double, null_t, null_t>>::value << '\n';
}
The padding is done by generating a list of null_ts using the dummy make_null_t alias template and a pack of indices of the right size.
One way to stop the recursion in your second example is to use boost.mpl. For example,
#include <boost/mpl/eval_if.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/integral_c.hpp>
template<int x>
struct Mine {
using type = typename boost::mpl::eval_if<boost::mpl::bool_<x == 12>,
boost::mpl::integral_c<short, 12>,
Mine<x+1>
>::type;
};
In the above example, it will always give you 12 as a value, regardless of the argument (as long as it is less or equal to 12).
As I understood you need to break recursion at Mine structure. If that is right, you can use full template specialization of this struct (for implementing terminal case of recursion). It looks like that:
template<>
struct Mine<123456>{
// It is struct represents end of recursion
};
It is simple example of usage this approach for computing factorial:
#include <iostream>
template <int N>
struct Factorial
{
static const int fact = N * Factorial<N - 1>::fact;
};
template <>
struct Factorial<0>
{
static const int fact = 1;
};
int main()
{
std::cout << Factorial<1>::fact << std::endl;
std::cout << Factorial<3>::fact << std::endl;
return 0;
}

Sum Nested Template Parameters at Compile Time

I'm looking for a better way to calculate the sum of numeric template parameters associated with nested template classes. I have a working solution here, but I want to do this without having to create this extra helper template class DepthCalculator and partial specialization DepthCalculator<double,N>:
#include <array>
#include <iostream>
template<typename T,size_t N>
struct DepthCalculator
{
static constexpr size_t Calculate()
{
return N + T::Depth();
}
};
template<size_t N>
struct DepthCalculator<double,N>
{
static constexpr size_t Calculate()
{
return N;
}
};
template<typename T,size_t N>
class A
{
std::array<T,N> arr;
public:
static constexpr size_t Depth()
{
return DepthCalculator<T,N>::Calculate();
}
// ...
// Too many methods in A to write a separate specialization for.
};
int main()
{
using U = A<A<A<double,3>,4>,5>;
U x;
constexpr size_t Depth = U::Depth(); // 3 + 4 + 5 = 12
std::cout << "Depth is " << Depth << std::endl;
A<double,Depth> y;
// Do stuff with x and y
return 0;
}
The static function A::Depth() returns the proper depth at compile time, which can then be used as a parameter to create other instances of A. It just seems like a messy hack to have to create both the DepthCalculator template and a specialization just for this purpose.
I know I can also create a specialization of A itself with a different definition of Depth(), but this is even more messy due to the number of methods in A, most of which depend on the template parameters. Another alternative is to inherit from A and then specialize the child classes, but this also seems overly complicated for something that seems should be simpler.
Are there any cleaner solutions using C++11?
Summary Edit
In the end, this is the solution I went with in my working project:
#include <array>
#include <iostream>
template<typename T,size_t N>
class A
{
std::array<T,N> arr;
template<typename U>
struct Get { };
template<size_t M>
struct Get<A<double,M>> { static constexpr size_t Depth() { return M; } };
template<typename U,size_t M>
struct Get<A<U,M>>
{ static constexpr size_t Depth() { return M + Get<U>::Depth(); } };
public:
static constexpr size_t GetDepth()
{
return Get<A<T,N>>::Depth();
}
// ...
// Too many methods in A to write a separate specialization for.
};
int main()
{
using U = A<A<A<double,3>,4>,5>;
U x;
constexpr size_t Depth = U::GetDepth(); // 3 + 4 + 5 = 12
std::cout << "Depth is " << Depth << std::endl;
A<double,Depth> y;
// Do stuff with x and y
return 0;
}
Nir Friedman made some good points about why GetDepth() should be an external function, however in this case there are other Get functions (not shown) which are appropriately member functions, and therefore it would make the most sense to have GetDepth() a member function too. I also borrowed Nir's idea of having the Depth() functions only call themselves, rather than GetDepth() which creates a bit less circular dependencies.
I chose skypjack's answer because it most directly provided what I had originally asked for.
You said:
I want to do this without having to create this extra helper template class DepthCalculator
So, maybe this one (minimal, working example) is fine for you:
#include<type_traits>
#include<cassert>
template<class T, std::size_t N>
struct S {
template<class U, std::size_t M>
static constexpr
typename std::enable_if<not std::is_arithmetic<U>::value, std::size_t>::type
calc() {
return M+U::calc();
}
template<typename U, std::size_t M>
static constexpr
typename std::enable_if<std::is_arithmetic<U>::value, std::size_t>::type
calc() {
return M;
}
static constexpr std::size_t calc() {
return calc<T, N>();
}
};
int main() {
using U = S<S<S<double,3>,4>,5>;
static_assert(U::calc() == 12, "oops");
constexpr std::size_t d = U::calc();
assert(d == 12);
}
I'm not sure I got exactly your problem.
Hoping this can help.
If you are with C++14, you can use also:
template<class U, std::size_t M>
static constexpr
std::enable_if_t<not std::is_arithmetic<U>::value, std::size_t>
If you are with C++17, it becomes:
template<class U, std::size_t M>
static constexpr
std::enable_if_t<not std::is_arithmetic_v<U>, std::size_t>
The same applies to the other sfinaed return type.
Option #1
Redefine your trait as follows:
#include <array>
#include <cstddef>
template <typename T>
struct DepthCalculator
{
static constexpr std::size_t Calculate()
{
return 0;
}
};
template <template <typename, std::size_t> class C, typename T, std::size_t N>
struct DepthCalculator<C<T,N>>
{
static constexpr size_t Calculate()
{
return N + DepthCalculator<T>::Calculate();
}
};
template <typename T, std::size_t N>
class A
{
public:
static constexpr size_t Depth()
{
return DepthCalculator<A>::Calculate();
}
private:
std::array<T,N> arr;
};
DEMO
Option #2
Change the trait into function overloads:
#include <array>
#include <cstddef>
namespace DepthCalculator
{
template <typename T> struct tag {};
template <template <typename, std::size_t> class C, typename T, std::size_t N>
static constexpr size_t Compute(tag<C<T,N>>)
{
return N + Compute(tag<T>{});
}
template <typename T>
static constexpr size_t Compute(tag<T>)
{
return 0;
}
}
template <typename T, std::size_t N>
class A
{
public:
static constexpr std::size_t Depth()
{
return Compute(DepthCalculator::tag<A>{});
}
private:
std::array<T,N> arr;
};
DEMO 2
You can do this wholly non-intrusively, which I think is advantageous:
template <class T>
struct Depth
{
constexpr static std::size_t Calculate()
{
return 0;
}
};
template <class T, std::size_t N>
struct Depth<A<T, N>>
{
constexpr static std::size_t Calculate()
{
return N + Depth<T>::Calculate();
}
};
Usage:
using U = A<A<A<double,3>,4>,5>;
constexpr size_t depth = Depth<U>::Calculate(); // 3 + 4 + 5 = 12
I realize your original question was how to do this without the extra "helper template", which my solution still has. But on the flip side, it's moved the functionality completely out of A itself, so its not really a helper template any more, it's just a template. This is pretty short, doesn't have any template template parameters unlike Piotr's solutions, is easy to extend with other classes, etc.

Variadic templates with constants

I'm doing some experimenting with metaprogramming and variadic templates, and I'm having trouble with some confusing behaviour. I've stripped it down to a minimum working example, but essentially I want to keep track of how many recursive calls I'm making. I want to do this by making the first template parameter an integer, while the second template parameter is a variadic list. In simplest form it looks like this:
template<typename... List>
struct initial_call{
static const int val = next_call<0, List...>::val;
};
template<int D, typename... List>
struct next_call {
static const int val = D;
};
So ignoring the fact that this code is pointless, it doesn't compile on VS2013, claiming "unexpected type 'List", on the line inside the definition of initial_call. Without the integer in front, it works fine. So is there a way to combine variadic templates with integer template parameters?
You might want something like this (counting the number of types):
#include <iostream>
// More than one type: Increment size and consume.
template<size_t N, typename T, typename... List>
struct calculate_list_size {
static const size_t value = calculate_list_size<N + 1, List...>::value;
};
// Last type: Increment size and terminate.
template<size_t N, typename T>
struct calculate_list_size<N, T> {
static const size_t value = N + 1;
};
// Forward to calculate_list_size.
template<typename... List>
struct list_size {
static const size_t value = calculate_list_size<0, List...>::value;
};
// Empty list
template<>
struct list_size<> {
static const size_t value = 0;
};
int main()
{
std::cout << list_size<char, short, int>::value << '\n';
std::cout << list_size<>::value << '\n';
}