I need to pass an array as a template type. How can achieve it. For example, I want something like this.
Fifo<array, Q_SIZE> f; // This is a queue of arrays (to avoid false sharing)
What should I put in place of array? Assume I need an array of int. Also note that I don't want std::vector or a pointer to an array. I want the whole basic array, something equivalent of say int array[32].
Try this:
Fifo<int[32], Q_SIZE> f;
Like this:
#include <iostream>
template <class T, int N>
struct Fifo {
T t;
};
int main () {
const int Q_SIZE = 32;
Fifo<int[32],Q_SIZE> f;
std::cout << sizeof f << "\n";
}
If you want to pass array type when creating queue you can write
template <typename Array>
struct Fifo;
template <typename T, int size>
struct Fifo<T[size]>
{
};
or just
template <typename Array>
struct Fifo
{
};
and use it like
int main()
{
Fifo<int[10]> fa;
}
Then, you should understand, that int[10] is completely different type from int[11], and once you created Fifo<int[10]> you cannot store here arrays of size 11 or 9 anymore.
The std::end function in C++ 11 has an overload for array types that nicely demonstrate this.
Here's a possible implementation of it:
template< class T, std::size_t N >
T* end(T(&array)[N]) {
return array + N;
}
If you need an object that wraps an array, a templated factory function will help creating it:
template< class T, std::size_t N >
struct fifo {
T(&array)[N];
};
template< class T, std::size_t N >
fifo<T,N> make_fifo(T(&array)[N]) {
return Fifo<T,N>{ array };
}
int main() {
int arr[] = { 1,2,3,4,5 };
// Create object from array using template argument deduction
auto fifo = make_fifo(arr);
}
Well I've found a solution. I can wrap the array in a structure, such as below.
typedef struct
{
int array[32];
} my_array;
Then I can use it as follows.
Fifo<my_array, Q_SIZE> f;
Related
This may be a bizarre question, but I have a recursive template that expects an array of size d (where d is a template parameter), and I want to pass the d-1 template the same array as if it was one element shorter. This way I only work with one array, instead of creating a new one for each level.
I feel like the answer may be something very basic, but I can't come up with any search terms that result in anything close to what I'm looking for.
To put this into context, here's an example
template<int d>
void Function(int array[d])
{
array[d- 1]= d;
Function<d- 1>(?);
}
This answer is for static, C-style arrays, If your question is about std::Array, I apologize.
Off the top of my head, I came up with two ways to do the recursion, but many more techniques exist.
The first one uses a partially specialized class (with array count of zero) to terminate the recursion.
The second way uses a cast to a statically-chosen type which ends the recursion with an overloaded function. Here, I cast the array to void*, but for types that won't work with this, you could create a custom type which is constructible from the original type.
I resorted to using reinterpret_cast to change the array's type from a reference to array[count] to array[count-1]. Although I expect this to be safe as it is used here, keep in mind that you might run into problems in different situations.
#include <iostream>
// Ends recursion with a partial specialization
template <typename T, int count>
struct StaticArrayDump {
static void func(T(&a)[count]) {
using shorter_t = T(&)[count-1];
StaticArrayDump<T, count-1>::func(reinterpret_cast<shorter_t>(a));
std::cout << a[count-1] << ' ';
}
};
template <typename T>
struct StaticArrayDump<T,0> {
static void func(...) {}
};
template <typename T, int count>
static void static_array_dump_spec(T(&a)[count]) {
using shorter_t = T(&)[count-1];
StaticArrayDump<T,count>::func(a);
}
// Ends recursion with void* cast and function overload
// Ultimately relies on type_select's specialization, however
template <bool, typename A, typename B> struct type_select /* true */ { using type = A; };
template <typename A, typename B> struct type_select<false,A,B> { using type = B; };
template <bool cond, typename A, typename B>
using type_select_t = typename type_select<cond, A, B>::type;
static void static_array_dump_ovld(...) {}
template <typename T, int count>
static void static_array_dump_ovld(T(&a)[count]) {
static const int next_count = count-1;
using shorter_t = T(&)[next_count];
static_array_dump_ovld(reinterpret_cast<
type_select_t<next_count!=0, shorter_t, void*>
>(a));
// output the last element
std::cout << a[count-1] << ' ';
}
// This is an overload-based version which is free of
// any reliance on template specialization.
// helper_trueol's (void*, void*) overload will only be
// selected for arguments (array_ref, count) when count
// is 0, because 0 is the only integer which can be
// converted to a pointer.
// This one's compiler compatibility is a bit shaky...
// MSVC 2013 OK
// IdeOne g++ needs int cast for next_count
static void helper_trueol(void*, void*) {}
template <typename T, int count>
static void helper_trueol(T(&a)[count], int) {
static const int next_count = count-1;
using shorter_t = T(&)[next_count];
helper_trueol(reinterpret_cast<shorter_t>(a), int(next_count));
std::cout << a[count-1] << ' ';
}
template <typename T, int count>
static void static_array_dump_trueol(T(&a)[count]) {
helper_trueol(a, count);
}
// Finally, this overload-based version relies
// on SFINAE to disqualify the template function
// as a candidate when count is 0 because the
// zero-length array type triggeres a substitution
// failure.
// So just using this template array argument type,
// the same one used in all of the previous examples,
// but without any extra mechanisms, is all you need
// to end this recursion!
// This is the obvious best way, of course.
static void static_array_dump_sfinae(...) {}
template <typename T, int count>
static void static_array_dump_sfinae(T(&a)[count]) {
static const int next_count = count-1;
using shorter_t = T(&)[next_count];
static_array_dump_sfinae(reinterpret_cast<shorter_t>(a));
std::cout << a[count-1] << ' ';
}
//////
int main() {
double dbl_array[] = { 0, 1.2, 3.4, 5.6789, 10 };
static_array_dump_spec(dbl_array);
std::cout << '\n';
const char* cstr_array[] = { "zero", "one", "two", "three", "four" };
static_array_dump_ovld(cstr_array);
std::cout << '\n';
char charray[] = "Hello";
charray[sizeof(charray)-1] = '!'; // replace nul terminator
static_array_dump_trueol(charray);
std::cout << '\n';
bool barray[] = {true, true, true, false, true, false, false, false};
std::cout << std::boolalpha;
static_array_dump_sfinae(barray);
std::cout << '\n';
}
Hopefully I am interpreting this correctly but, when you pass the array as a template, I assume you pass an argument for the size of the array. (otherwise how would you know how large the array is?) When you pass the array, you are passing a pointer to the first element of the array, so when you pass the sub array you could just pass a pointer to the next element and size d-1 or an iterator that points to the next element and size d-1.
Example:
template< typename T>
T foo(T * ptr, int size) {
if (size > 0)
return *ptr + foo(ptr + sizeof(T), size - 1);
else
return 0;
}
From the information that you provided i assume you want too know how too "stop" the recursion. This would look something like this:
// this is the function that will be called from the user, it would be bad design too have to pass an integral constant manually when we can easily do this
template <std::size_t I>
inline
void Function(int (&_array)[I])
{
Function(_array, std::integral_constant<std::size_t, I>);
}
// function will recursively do something with an array for each of it's elements
template<std::size_t I>
void Function(int (&_array)[I], std::integral_constant<std::size_t, I>)
{
// do something...
Function(_array,std::integral_constant<std::size_t,I-1>);
}
// function as before with a few modifications
template<std::size_t I>
void Function(int (&_array)[I], std::integral_constant<std::size_t, 1>)
{
// do something...
// exit function...
}
I have the following template class:
template <unsigned N>
class XArray {
static const int Xdata[N];
};
I want to initialize the static const array for each XArray<N> I used, for example, let XArray<N>::Xdata = {1, 2, 3, ..., N}. How to make it?
you declared a static const int array in your class,so you must define the static member out of the class declaration,just like this:
template<unsigned N>
class XArray
{
public:
static const int array[N];
};
template<unsigned N>
const int XArray<N>::array[N] = {1,2,3,4,5};
But something you must pay attention to is that: when you use this template you must make sure that the "N" bigger than the number of your initialized array;
EDIT:
It seems someone have already provided the solution for your problem in other question, and the answer is quite the same as mine.
Also, for more generic answer, you can check out answers to this question.
Code
If you don't mind using C++11 features, then variadic templates may come handy:
template <unsigned ...Args>
struct XArrayData
{
static const int Values[sizeof...(Args)];
};
template<unsigned N, unsigned ...Args>
struct _XArrayGenerator
{
typedef typename _XArrayGenerator<N - 1, N, Args...>::Xdata Xdata;
};
template<unsigned ...Args>
struct _XArrayGenerator<1, Args...>
{
typedef typename XArrayData<1, Args...> Xdata;
};
template<unsigned N>
struct XArray
{
typedef typename _XArrayGenerator<N>::Xdata Xdata;
};
template <unsigned ...Args>
const int XArrayData<Args...>::Values[sizeof...(Args)] = { Args... };
Explanation
XArray template struct takes the number of array elements as a template parameter (N). In the compilation time, it uses _XArrayGenerator to generate template paremeter list with N consecutive numbers. It begins with the number N, and then recursively uses itself until it reaches 1. At this point, the template parameter list looks like this:
1, 2, ..., N
The last thing to do is to pass these parameters to XArrayData. The last line of the code (definition of the actual array) uses the parameters to initialize the array.
Usage
for (int i = 0; i < 3; ++i)
cout << XArray<3>::Xdata::Values[i] << endl;
Output:
1
2
3
You can initialize as shown below. See inline comments for my explanation.
template <unsigned N>
class XArray {
private:
static const int Xdata[N];
public:
//I added this for illustration purpose
void print()
{
for (int i = 0; i < N; ++i)
{
std::cout << Xdata[i] << std::endl;
}
}
};
//you can initialize like this
//automatic size counting works with static arrays
//here I initialize with 3 elements
//make sure you don't use N < 3 anywhere
template <unsigned N>
const int XArray<N>::Xdata[] = {1,2,3};
int main(void)
{
XArray<3> obj1; //N = 3: This is okay.
XArray<8> obj2; //N > 3: This is okay. Remaining elements will be 0.
XArray<2> obj3; //N < 3: This is also okay.
obj1.print();
obj2.print();
obj3.print(); //but this will give compilation error
return 0;
}
In continuation of this topic Variadic template heterogeneous container, I would like to ask the following. Assume, that we have several classes with two members that is dynamic arrays. Now suppose that there is a sequence of objects of these classes, which is packed in heterogeneous container. In this sequence one of arrays-mebers is "output" vector and another array-member is "input" vector, which is pointer to appropriate output array from preceding object. This sequence is implemented as variadic template class:
//Classes, objects which are members of the sequence
template<int NumberElements>
struct A
{
A() : output(new float[NumberElements]){}//allocate output
~A(){delete[] output;}
float *input;//input vector - pointer to output vector from preceding object of sequence
float *output;// output vector (size - NumberElements) of current member of sequence
};
template<int NumberElements>
struct B
{
B() : output(new float[NumberElements]){}//allocate output
~B(){delete[] output;}
float *input;
float *output;
};
template<int NumberElements>
struct C
{
C() : output(new float[NumberElements]){}//allocate output
~C(){delete[] output;}
float *input;
float *output;
};
//Container
template<typename...Arg>
struct HeterogenousContainer
{
HeterogenousContainer();//Do something to setup the sequence
std::tuple<Arg...> elements;
};
How can I properly allocate memory (via new/malloc) for output vectors, and set up input pointers to preceding output vectors? For example, I write next code:
HeterogenousContainer<A<5>, B<7>, C<9>> sequence;
I want that input from first member of sequence to be nullptr, input from second - points to output from first, etc. How to implement it correctly?
Firstly, don't mess around with manual (de)allocation if you can avoid it. For a simple array, you can:
#include <array>
#include <tuple>
template<int NumberElements>
struct A
{
float *input;
std::array<float, NumberElements> output;
};
You just need to recurse down the tuple, and specialize for the termination case. I'm doing it backwards since the first element is your special case.
namespace detail {
template <int N> struct Connector;
template <>
struct Connector<0> {
template <typename... TL> static void connect(std::tuple<TL...> &t) {
std::get<0>(t).input = nullptr;
}
};
template <int N> struct Connector {
template <typename... TL> static void connect(std::tuple<TL...> &t) {
std::get<N>(t).input = &std::get<N-1>(t).output.front();
Connector<N-1>::connect(t);
}
};
template <typename... TL> void connect(std::tuple<TL...> &t) {
Connector<sizeof...(TL)-1>::connect(t);
}
}
and use it something like this:
template <typename... Arg> struct HeterogenousContainer {
std::tuple<Arg...> elements;
HeterogenousContainer() { detail::connect(elements); }
};
Inspired by Useless' answer (no pun intended), I came up with this:
template<typename...Arg>
struct HeterogenousContainer
{
std::tuple<Arg...> elements;
void init(std::integral_constant<std::size_t, 0>)
{
std::get<0>(elements).input = nullptr;
}
template < std::size_t index = sizeof...(Arg)-1 >
void init(std::integral_constant<std::size_t, index> = {})
{
std::get<index>(elements).input = std::get<index-1>(elements).output;
init(std::integral_constant<std::size_t, index-1>{});
}
HeterogenousContainer()
: elements{}
{
init();
}
};
I am a bit in stuck and need a help from C++ template guru. There is a template struct:
template<typename T, typename ID>
struct TypeMapping
{
T Type;
char* Name;
ID Id;
};
and a few template functions like this:
template<typename T, typename ID>
bool TryGetTypeByNameImp(const TypeMapping<T, ID> map[], size_t mapSize,
const char* name, T& type)
{
for (size_t i = 0; i < mapSize; i++)
{
if (strcmp(map[i].Name, name) == 0)
{
type = map[i].Type;
return true;
}
}
return false;
}
Map (the first parameter) is defined as (there are a few similar maps)
namespace audio
{
const TypeMapping<Type, AMF_CODEC_ID> Map[] =
{
{AAC, "aac", AMF_CODEC_AAC},
{MP3, "mp3", AMF_CODEC_MP3},
{PCM, "pcm", AMF_CODEC_PCM_MULAW}
};
const size_t MapSize = sizeof(Map)/sizeof(Map[0]);
}
Map is passed to a function as an argument and I am looking for how to pass it as template parameter so I can use functions like in this sample:
audio::Type type;
bool r = TryGetTypeByNameImp<audio::Map>("aac", type);
The only solution I found it is to define a struct which holds static Map and MapSize and use the struct as template parameter but I do not like this solution and I am looking for another one. Does anybody know how to do this?
bool r = TryGetTypeByNameImp<audio::Map>("aac", type);
This is trying to use audio::Map as a type – but it isn’t, it’s a variable. Just pass it to the function as a normal argument:
bool r = TryGetTypeByNameImp(audio::Map, "aac", type);
That said, I have three remarks about your code:
Be aware that declaring a function argument as an array (x[]) does in reality declare it as a pointer. Your code uses this correctly, but using the array syntax is misleading. Use a pointer instead.
This code is slightly too C-heavy for my taste. While I agree that using raw C-strings is appropriate here, your usage of char* is illegal in C++11, and deprecated in C++03 (since you are pointing to string literals). Use char const*. Furthermore, I’d suggest using a std::string argument in the function, and using the comparison operator == instead of strcmp.
You are using an out-parameter, type. I abhor this technique. If you want to return a value, use the return type. Since you also return a success value, use a pair as the return type, unless there’s a very compelling reason not to:
template<typename T, typename ID>
std::pair<bool, T> TryGetTypeByNameImp(
const TypeMapping<T, ID> map[], size_t mapSize,
const char* name)
{
for (size_t i = 0; i < mapSize; i++)
if (strcmp(map[i].Name, name) == 0)
return std::make_pair(true, map[i].Type);
return std::make_pair(false, T());
}
Ah, and I’d also consider using a std::vector or std::array here instead of a C array. Then you don’t need to manually shlep the array size around through all the functions which use the array.
You can certainly use the array itself (well, a pointer to it) as a template parameter:
#include <iostream>
template<typename T> struct S { T t; };
S<int> s[] = { { 21 }, { 22 } };
template<typename T, size_t n, S<T> (*m)[n]> void f() { std::cout << (*m)[n - 1].t; }
int main() {
f<int, 2, &s>();
}
The problem here is that you can't use template argument deduction on the length of the array nor on its type, so both must be supplied as template parameters in addition to the array itself. I really think that passing in a struct or, say a vector would be the better solution, as you've no doubt already explored:
#include <vector>
#include <iostream>
template<typename T> struct S { T t; };
std::vector<S<int>> s{ { 21 }, { 22 } };
template<typename T, std::vector<S<T>> *v> void f() { std::cout << v->back().t; }
int main() {
f<int, &s>();
}
What type signature would I need to use if I'd like to determine the type returned by an array (T)'s subscript operator using boost? Note that the arrays for which I would be using this do not contain typedefs and are third-party.
Example. I want to determine that:
SomeArray<int> tmp(1);
int& somevalue = tmp[0]; //would equate
typename subscript_result<SomeArray<int> >::type somevalue = tmp[0];
Something like
template<class T>
struct subscript_result
{
typedef boost::result_of<T::operator[](typename T::difference_type)>::type type;
};
? I've always had trouble with operator[] in type signatures. :|
Thank you!
Perhaps you could use BOOST_TYPEOF / BOOST_TYPEOF_TPL: http://www.boost.org/doc/libs/1_35_0/doc/html/typeof/refe.html#typeof.typo
BOOST_TYPEOF(tmp[0]) i;
In C++0x, you should be able to use decltype(tmp[0]) i;
In answer to the comment. Perhaps you can trick it to not remove const and references with something like that:
#include <boost/typeof/typeof.hpp>
template <class T>
struct identity
{
typedef T type;
};
template <class T>
struct subscript_result
{
template <class Result, class Obj, class Arg>
static identity<Result> get_subscript_type(Result (Obj::*)(Arg));
typedef BOOST_TYPEOF(get_subscript_type(&T::operator[])) aux;
typedef typename aux::type type;
};
#include <vector>
#include <iostream>
template <class Container>
void foo(Container& c)
{
typename subscript_result<Container>::type t = c[0];
++t;
}
int main()
{
//prove that foo gets a reference to vector<int>
std::vector<int> vec(1);
foo(vec);
std::cout << vec[0] << '\n';
}
You'll probably also need to come up with something for const overloads, as well as throw in specializations for arrays / pointers.