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...
Related
I'm working on a C++11 wrapper around a C api. The C api offers a bunch of getters for various types, with a different name for each type. Values are retrieved by array of a given size, known at compilation.
I want to give the type and the array size by template, to call the right function.
#include <string>
#include <iostream>
template <typename T>
struct make_stop {
constexpr static bool value = false;
};
class Foo
{
public:
Foo() : i(42) {}
template<typename T, size_t n>
T get();
private:
int i = 0;
};
template<typename T, size_t n>
T Foo::get() { static_assert(make_stop<T>::value); return T(); }
template<int, size_t n>
int Foo::get() { return i + n; }
int main() {
Foo foo;
int i = foo.get<int, 4>();
double f = foo.get<double, 2>();
return 0;
}
But it fails to match the right function
main.cpp:26:5: error: no declaration matches 'int Foo::get()'
int Foo::get() { return i + n; }
^~~
main.cpp:15:7: note: candidate is: 'template<class T, long unsigned int n> T Foo::get()'
T get();
its a bit vauge from your question, but assuming you are wanting to index into some c- arrays and return the value at I you can't specialize function templates like you want, but you can use some tags instead, something like..
class Foo
{
public:
Foo() : is{1,2,3,4,5,6,7,8,9,10},ds{1.1,2.2,3.3,4.4,5.5,6.6,7.7,8.8,9.9,10.1} {}
template <typename T> struct type_c{};
template <size_t I> struct int_c{};
template<typename T,size_t I>
auto get()
{ return get_impl(type_c<T>(),int_c<I>()); }
private:
template <size_t I>
auto get_impl(type_c<int>,int_c<I>)
{ return is[I]; }
template <size_t I>
auto get_impl(type_c<double>,int_c<I>)
{ return ds[I]; }
int is[10];
double ds[10];
};
int main() {
Foo foo;
int i = foo.get<int,0>();
double d = foo.get<double,2>();
std::cout << i << " " << d << std::endl;
return 0;
}
Demo
If I understood you correctly you want to partially specialize get for T. Unfortunately partial specialization for methods is not allowed by the standard. You can however get around this with a static method on a class templated by T and specializing the class.
Like this:
template <class T> struct Foo_helper;
struct Foo
{
Foo() : i{42} {}
template<class T, std::size_t N>
T get()
{
return Foo_helper<T>::template get<N>(*this);
}
int i = 0;
};
template <class T> struct Foo_helper {};
// specialize Foo_helper for each type T you wish to support:
template <> struct Foo_helper<int>
{
template <std::size_t N>
static int get(const Foo& foo) { return foo.i + N; }
};
template <> struct Foo_helper<double>
{
template <std::size_t N>
static double get(const Foo& foo) { return foo.i + N; }
};
int main()
{
Foo foo{};
int i = foo.get<int, 4>();
double d = foo.get<double, 2>();
}
I'm trying to do a templated class that runs a function only in certain cases. This is my code:
#include "stdafx.h"
#include <string>
#include <iostream>
template <class T, class U>
struct Typelist
{
typedef T Head;
typedef U Tail;
};
class NullType
{
};
typedef Typelist<int, Typelist<float, Typelist<char*, NullType> > > UsableTypes1;
typedef Typelist<short, Typelist<std::string, NullType> > UsableTypes2;
template <class T>
class MyClass
{
public:
MyClass();
private:
Typelist _types;
};
template<class T>
MyClass<T>::MyClass()
{
_types = T;
}
template<class T>
void MyClass<T>::print(T type)
{
}
MyClass<UsableTypes1> any;
I need to make the code compiler or not only if the variable I pass to the print() function is a type that is in one of the usable types. I know that probably I'll have to use std::enable_if to allow the code to compile or not if print is called with an incorrect type and std::is_same to check the types but I don't know how to combine that functions with a templated class.
This is a test class to help to explain what I want to achieve:
MyClass<UsableTypes1> one;
void TestMyClass()
{
int int_val = 0;
float flt_val = 0.1f;
const char* char_val = "Hi";
short short_val = 10;
std::string str_val = "Hello";
one.print(int_val); // OK
one.print(flt_val); // OK
one.print(char_val); // OK
// one.print( short_val); // compile error
// one.print( str_val ); // compile error
}
Specially I don't know how can I add to print() a non-T-type parameter.
I hope you can help me!
Thank you in advance.
I don't know if you have a good reason for using recursive Typelists to contain your list of types. A more straight forward way would be to make Typelist a variadic template.
Then we can add a constexpr function that returns true if a given type is part of the Typelist.
std::disjunction requires c++17, but something equivalent can be written for c++11 with a recursive template. That will however be more verbose.
#include <iostream>
#include <type_traits>
struct NullType {};
template <typename T, typename U>
struct Typelist {
using Head = T;
using Tail = U;
template <typename Type>
static constexpr bool IsUsable() {
return std::is_same<Type, T>::value;
}
};
template <typename T, typename... U>
struct Typelist<T, Typelist<U...>> {
using Head = T;
using Tail = Typelist<U...>;
template <typename Type>
static constexpr bool IsUsable() {
return std::is_same<Type, T>::value || Typelist<U...>::template IsUsable<Type>();
}
};
using UsableTypes1 = Typelist<int, Typelist<float, Typelist<const char*, NullType>>>;
template <class T>
class MyClass
{
public:
template <typename U>
void print(U u) {
static_assert(T::template IsUsable<U>(), "That is not a usable type");
std::cout << u << std::endl;
}
};
MyClass<UsableTypes1> one;
int main()
{
int int_val = 0;
float flt_val = 0.1f;
const char* char_val = "Hi";
short short_val = 10;
std::string str_val = "Hello";
one.print(int_val); // OK
one.print(flt_val); // OK
one.print(char_val); // OK
// one.print( short_val); // compile error
// one.print( str_val ); // compile error
}
Question to C++ template gurus:
I have created two template "policies" (not sure if this is the right term), which implement storage of some value types in a vector of either dumb or smart pointers:
#include <algorithm>
#include <iostream>
#include <memory>
#include <string>
#include <unordered_map>
#include <vector>
template <typename T>
class DumbPtrVec
{
std::vector<T*> m_vec;
public:
using handle = size_t;
~DumbPtrVec() {
std::for_each(begin(m_vec), end(m_vec), [](T* p){ delete p; });
}
handle AddElement(T* p) {
const handle index = m_vec.size();
m_vec.push_back(p);
return index;
}
T* GetElement(const handle& i) {
T* p = (i < m_vec.size())? m_vec[i] : nullptr;
return p;
}
};
template <typename T>
class SmartPtrVec
{
std::vector<std::shared_ptr<T>> m_vec;
public:
using handle = std::weak_ptr<T>;
handle AddElement(T* p) {
m_vec.emplace_back(p);
return m_vec.back(); // gets converted to weak_ptr
}
T* GetElement(const handle& i) {
T* p = (i.expired())? nullptr : i.lock().get();
return p;
}
};
template <typename T, template<typename> typename STORAGE>
class Storage
{
STORAGE<T> m_values;
public:
using handle = typename STORAGE<int>::handle;
handle AddValue(T* v) { return m_values.AddElement(v); }
T* GetValue(handle h) { return m_values.GetElement(h); }
};
int main()
{
constexpr int N = 13;
Storage<int, DumbPtrVec> d;
auto dh = d.AddValue(new int(N));
std::cout << *d.GetValue(dh) << " == " << N <<std::endl;
Storage<int, SmartPtrVec> s;
auto sh = s.AddValue(new int(N));
std::cout << *s.GetValue(sh) << " == " << N << std::endl;
return 0;
}
Everything works fine, so far.
Then I added a template wrapper, that replaces the element "handle" with a unique string and keeps a look-up table for converting strings back to the handles. If this class is explicitly derived from either DumbPtrVec or SmartPtrVec class, everything works, e.g. for SmartPtrVec:
template <typename T>
class StringHandleWrapper : SmartPtrVec<T>
{
using super = typename SmartPtrVec<T>;
using Str2HandleMap = std::unordered_map<std::string, typename super::handle>;
Str2HandleMap m_Name2HandleMap;
public:
using handle = std::string;
handle AddElement(T* p) {
typename super::handle elem = super::AddElement(p);
static int counter = 0;
std::string uuid = std::to_string(++counter);
m_Name2HandleMap[uuid] = elem;
return uuid;
}
T* GetElement(const handle& uuid) {
auto it = m_Name2HandleMap.find(uuid);
return (it != m_Name2HandleMap.end())? super::GetElement(it->second) : nullptr;
}
};
and successful invocation:
Storage<int, StringHandleWrapper> s;
std::string handle = s.AddValue(new int(N));
But I can't figure out how to add a second template parameter, STORAGE, to StringHandleWrapper, so that it could wrap any of DumbPtrVec or SmartPtrVec...
If I change StringHandleWrapper to:
template <typename T, template<typename> typename STORAGE>
class StringHandleWrapper : STORAGE<T>
{
using super = typename STORAGE<T>;
//... rest unchanged
then I can't figure out how to instantiate Storage class, as compiler complains about "too few template arguments":
Storage<int, StringHandleWrapper<SmartPtrVec>> s;
I hope I'm missing something simple...
Thank you for taking your time to look through my long question!
Create another level of template for partial argument application:
template <template <typename, template<typename> typename> class W,
template <typename> typename S>
struct Apply
{
template <typename T> using type = W<T, S>;
};
Then instantiate Storage like this:
Storage<int, Apply<StringHandleWrapper, SmartPtrVec>::type> s;
Just found the answer (it was indeed simple):
I needed to introduce two single-parameter templates
template<typename T> using StringDumbHandleWrapper = StringHandleWrapper<T, DumbPtrVec>;
template<typename T> using StringSmartHandleWrapper = StringHandleWrapper<T, SmartPtrVec>;
and use the new names in Storage instantiation, e.g.
Storage<int, StringDumbHandleWrapper> s;
So much for the long question... :)
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.
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;
}