C++ Template Class Constructor with Variable Arguments - c++

Is it possible to create a template function that takes a variable number of arguments, for example, in this Vector< T, C > class constructor:
template < typename T, uint C >
Vector< T, C >::Vector( T, ... )
{
va_list arg_list;
va_start( arg_list, C );
for( uint i = 0; i < C; i++ ) {
m_data[ i ] = va_arg( arg_list, T );
}
va_end( arg_list );
}
This almost works, but if someone calls Vector< double, 3 >( 1, 1, 1 ), only the first argument has the correct value. I suspect that the first parameter is correct because it is cast to a double during the function call, and that the others are interpreted as ints and then the bits are stuffed into a double. Calling Vector< double, 3 >( 1.0, 1.0, 1.0 ) gives the desired results. Is there a preferred way to do something like this?

Alas, right now there's no good way to do this. Most of the Boost packages that need to do something similar use macro tricks to define things like this:
template < typename T >
Vector< T >::Vector( T )
{ ... }
template < typename T, uint C >
Vector< T, C >::Vector( T t, C c1 )
{ ... }
template < typename T, uint C >
Vector< T, C >::Vector( T t, C c1, C c2 )
{ ... }
template < typename T, uint C >
Vector< T, C >::Vector( T t, C c1, C c2, C c3 )
{ ... }
The macros generate some set number (typically around 10) versions, and provide a mechanism to change the max number of parameters before expanding the construction.
Basically, its a real pain which is why C++0x is introducing variable-length template arguments and delegation methods that will let you do this cleanly (and safely). In the meantime you can either do it with macros, or try a C++ compiler that has support for (some of) these new experimental features. GCC is a good one for this.
Be warned though that since C++0x isn't actually out yet, things can still change and your code may not be in sync with the final version of the standard. Plus, even after the standard comes out, there'll be 5 years or so during which many compilers will only partially support the standard, so your code won't be very portable.

This code looks dangerous and I think your analysis on why it isn't working is spot on, there's no way for the compiler to know that when calling:
Vector< double, 3 >( 1, 1, 1 )
the ones should be passed as doubles.
I would change the constructor to something like:
Vector< T, C >::Vector(const T(&data)[C])
instead, and have the user pass the arguments as an array. Another sort of ugly solution would be something like this:
template < typename T, uint C >
Vector< T, C >::Vector(const Vector<T, C - 1>& elements, T extra) {
}
and call it like this (with some typedefs):
Vector3(Vector2(Vector1(1), 1), 1);

You can do what you want, but don't do it, because it's not typesafe. Best pass a vector of T or a pair of iterators containing those values.
template < typename T, uint C >
Vector< T, C >::Vector(int N, ... )
{
assert(N < C && "Overflow!");
va_list arg_list;
va_start(arg_list, N);
for(uint i = 0; i < N; i++) {
m_data[i] = va_arg(arg_list, T);
}
va_end(arg_list);
}
Vector<int> v(3, 1, 2, 3);
This can be better solved, since all the elements are homogeneous typed anyway.
template < typename Iter, uint C >
Vector< T, C >::Vector(Iter begin, Iter end)
{
T *data = m_data;
while(begin != end)
*data++ = *begin++;
}
int values[] = { 1, 2, 3 };
Vector<int> v(values, values + 3);
Of course, you have to make sure there is enough place in m_data.

Does TypeList fit your needs?
Generic Programming:Typelists and Applications
Loki C++ Library
Tiny Template Library: implementing typelist

In C++0x (really should be called C++1x), you can use template varargs to achieve what you want in a typesafe fashion (and you won't even need to specify the number of arguments!). However, in the current version of C++ (ISO C++ 1998 with 2003 amendments), there is no way to accomplish what you want. You can either hold off or do what Boost does, which is use preprocessor macro magic to repeat the definition of the constructor multiple times with different numbers of parameters up to a hard-coded, but large limit. Given that Boost.Preprocessor is kind of complicating, you could just define all of the following yourself:
Vector<T,C>::Vector();
Vector<T,C>::Vector(const T&);
Vector<T,C>::Vector(const T&, const T&);
// ...
Since the above is kind of painful to do by hand, though, you could write a script to generate it.

std::tr1::array (which looks similar to yours) does not define a constructor, and can be initialized as an aggregate (?)
std::tr1::array<int, 10> arr = {{ 1, 2, 3, 4, 5, 6 }};
Also you could check out Boost.Assignment library.
For example the constructor could be
template < typename T, uint C >
template < typename Range >
Vector< T, C >::Vector( const Range& r )
and instances created with
Vector<int, 4> vec(boost::assign::cref_list_of<4>(1)(3)(4)(7));

You can use variadic , variadic means template with variable argument.more

The problem with variable arguments in constructors is :
you need the cdecl calling convention (or another one that can handle varargs)
you cant define cdecl for a constructor (in MSVS)
So the "correct" code (MS) could be :
template < typename T, uint C > __cdecl Vector< T, C >::Vector( T, ... )
but the compiler will say:
illegal calling convention for constructor/destructor (MS C4166)

Related

Partial template argument deduction or workaround for std::array?

C++17 allows us to have std::array's template arguments deduced. E.g., I can write
std::array ints = { 1, 2, 3 };
and ints will be of type std::array<int, 3>.
My question is: what if I wanted to specify only the type argument of the array but have the size of the array automatically determined?
The following does not work since it seems like all template arguments have to be specified:
std::array<size_t> sizes = { 1, 2, 3 };
My compiler complains and says: 'std::array': too few template arguments.
Is it possible to have the size of the array determined automatically by template argument deduction? If not, is it possible to create an array by only specifying its type but not its size?
As far as I know, this cannot be done. But a helper method does the trick:
template<typename Type, typename ... T>
constexpr auto makeArray(T&&... t) -> std::array<Type, sizeof...(T)>
{
return {{std::forward<T>(t)...}};
}
Usage example:
const auto container = makeArray<double>(-5.0, 0.0, 5.0, 10.0);
If, I might be so bold as to expand on the Benjamin's answer. Conceptually one does not need always to be explicit about the result type.
template<
typename ... T,
typename CT = std::common_type_t< T... >
>
constexpr auto make_array(T&& ... t)
-> std::array< CT , sizeof...(T)>
{
return { { static_cast<CT>( std::forward<T>(t) ) ...} };
}
Slightly simpler usage
constexpr auto std_arr = make_array(-5.0, 0.0, 5.0, 10.0);
The issue here might be, we are not exactly certain, what type of the std::array we will get. Provided we do care about it.
const auto std_arr = make_array(-5.0, 0, 5.0, 10.0, 42.13f );
Over "here", using MSVC, the latest, I get std array of doubles. If one's bed time reading is ISO C++ standard doc, the one might be sure what type will come out of std::common_type from the tool chain in use.
For the rest of us, literal suffixes will help
constexpr auto sizes = make_array( 1UL, 2UL, 3UL );
But why stop with numbers? One can collect quickly, into an array, instances from the same hierarchy. Not caring about the result type.
{
const auto exceptions = make_array(
std::exception{"SE"},
std::runtime_error{"RE"},
std::logic_error{"LE"} );
}
A bit useless but somewhat weird and wonderful. One thing thou remember: this is compile time situation. Thus, I might prefer:
constexpr auto sizes = std::array{ 1UL, 2UL, 3UL } ;
To answer the OP's question directly.
There is also C++20 std::to_array. For the exact result type and for a bit more comfortable usage:
constexpr auto sizes = std::to_array<size_t>({ 0, 1, 3 });
Enjoy ...

For loop index type deduction best practice

Let's say, I have a container c of a type that provides a size() method and I want to loop over this container while keeping track of each item's index:
for (/*TODO*/ i = 0; i < c.size(); i++) {...}
In a post-C++11 world, where automatic type deduction solves so many problems nicely. What should we use in place of the TODO above? The only thing that seems correct to me, no matter what the type of size() is, is the following:
for (decltype(c.size()) i = 0; i < c.size(); i++) {...}
But this seems overly verbose and ,in my opinion, doesn't help readability.
Another solution might be this:
for (auto end = c.size(), i = 0; i < end; i++) {...}
But this doesn't help readability either and, of course, doesn't have the same semantics as the original snippet.
So, my question is: what is the best way to deduce the type of a loop index variable, given only the type of the index' limit.
Short answer to the first question in your text: You should replace the /*TODO*/ by unsigned, std::size_t or something similar, meaning: don't bother deducing the type, just pick a type suitable for any reasonable container size.
This would be an unsigned, reasonably large type so the compiler is not tempted to yell at you beacuse of possible precision losses. In the comments above you write that size_t is not guaranteed to be a good replacement to decltype(c.size()), but while it is not impossible to implement a container that has an index incompatible to size_t, such indizes would most surely not be numbers (and thus incompatible to i = 0), and the containers would not have a size method either. A size() method implies a nonnegative integral, and since size_t is designed for exact those numbers, it will be close to impossible to have a container of a size that cannot be represented by it.
Your second question aims at how to deduce the type, and you already have provided the easiest, yet imperfect answers. If you want a solution that is not as verbose as decltype and not as surprising to read as auto end, you could define a template alias and a generator function for the starting index in some utility header:
template <class T>
using index_t = decltype(std::declval<T>().size());
template <class T, class U>
constexpr index_t<T> index(T&&, U u) { return u; }
//and then in the actual location of the loop:
for (auto i = index(c,0); i < c.size(); ++i) {...}
//which is the same as
for (auto i = index_t<std::vector<int>>(0); i < c.size(); ++i) {...}
If you want to have a more general index-type, e.g. for arrays and classes that don't have a size method, it gets a bit more complicated, because template aliases may not be specialized:
template <class T>
struct index_type {
using type = decltype(std::declval<T>().size());
};
template <class T>
using index_t = typename index_type<T>::type;
template <class T, class U>
constexpr index_t<T> index(T&&, U u) { return u; }
//index_type specializations
template <class U, std::size_t N>
struct index_type<U[N]> {
using type = decltype(N);
};
template <>
struct index_type<System::AnsiString::AnsiString> { //YUCK! VCL!
using type = int;
};
However, this is a lot of stuff just for the few cases where you actually need an index and a simple foreach loop is not sufficient.
If c is a container you can use container::size_type.
Here is the precedence that I follow
1) range-for
2) iterator/begin()/end() with type deduced with auto.
For cases where indexing is required, which is the subject here, I prefer to use
for( auto i = 0u; i < c.size(); ++i) {...}
Even if I misses to add u in 0, compiler will warn me anyway.
Would have loved decltype if it is not too verbose
for (decltype(c.size()) i = 0; i < c.size(); i++) {...}
Hmm... this needs C++14 or a compiler that supports auto in the lambda parameters. If you're using this pattern a lot, then a helping function might be useful:
template< typename Container, typename Callable >
void for_each_index( Container& container, Callable callable )
{
for (decltype(container.size()) i = 0; i < container.size(); i++)
{
callable(i);
}
}
Use as:
for_each_index(c, [] (auto index) {
// ...
});
As a matter of fact, I have seen plenty of times (cough llvm, clang) where they do use
for (/* type */ iter = begin(), End = end(); iter != End; ++i);
The advantage of having End evaluated at the beginning is that the compiler can be sure that it doesn't need to call it every time. For collections that where calculating the end is trivial and the compiler is already able to deduce that it doesn't need to call end() multiple times it won't help, but in other cases it will.
Or you could always use a helper:
Implementing enumerate_foreach based on Boost foreach

Change member-typedef depending on template parameter?

I have this problem here that I can’t figure out how to solve. I want a template class that takes an integer as template parameter and sets the template parameters for another class accordingly:
template <int T>
class Solver
{
public:
#if T <= 24
typedef MyMatrix<float> Matrix;
#else if T <= 53
typedef MyMatrix<double> Matrix;
#else
typedef MyMatrix<mpreal> Matrix;
#endif
Matrix create();
};
And then calling it like this:
Solver<53>::Matrix m = Solver<53>::create();
How can I do something like this? At the moment with the code above, the compiler complaints that it doesn't know "Matrix", so I'm not sure if you can use the preprocessor on template parameters.
INTRODUCTION
Since you'd like S<N>::Matrix to yield a different type depending on the N passed, you will need to use some sort of meta template programming. The question is currently tagged with preprocessor, and the snippet explicitly tries to use it; but that is of little to no use in this case.
When the code is being preprocessed N is nothing more than a name, it hasn't got a value; yet.
Solution
The description mentiones if, if ... else, and else; and we are dealing with types.. looking through <type_traits> it seems like std::conditional would be a perfect match!
std::conditional<condition, type-if-true, type-if-false>::type;
Note: Depending on whether the expression found in condition yields true, or false, ::type will be a typedef for either type-if-true, or type-if-false.
Let's write a sample implementation:
#include <type_traits>
template <int N>
class Solver
{
public:
typedef typename std::conditional<
/* */ (N <= 24),
/* y? */ MyMatrix<float>,
/* n? */ typename std::conditional<(N <= 53), MyMatrix<double>, MyMatrix<mpreal>>::type
>::type matrix_type;
...
};
int main () {
Solver<53>::matrix_type a; // Matrix<double>
Solver<10>::matrix_type b; // Matrix<float>
Solver<99>::matrix_type c; // Matrix<mpreal>
}
You can use std::conditional for this, although whether you should be doing this in the first place is another kettle of fish:
template<int T>
class Solver
{
std::conditional_t<
T <= 24,
MyMatrix<float>,
std::conditional_t<
T <= 53,
MyMatrix<double>,
MyMatrix<mpreal>
>
> Matrix;
};
You'll need to use std::conditional and ::type instead of conditional_t if your compiler doesn't support it.
No, you can't use the preprocessor on template parameters.
The preprocessor is just doing very simple string processing on your input source. It has no glue about types and I think it is run as the very first step while first processing the file and collecting all the includes. Templates are something the compiler itself takes care of. At this point the preprocessor has finished already.
A similar question has been asked here:
Use a template parameter in a preprocessor directive?

Can I use value_type on an instance of the vector, not on its type

while playing and trying to calculate total size of vector I tried something like
vector<double> vd;
auto area = vd.size()* sizeof (vd::value_type);
//Ive seen Stepanov use area as name for this kind of size, idk if he adds the sizeof vd also to area :)
Unfortunately this doesnt work...
I need to use vector<double>::value_type but that makes code less readable.
Can it be made to work? I dont like sizeof vd.front() because it just looks ugly to write front() for this.
EDIT: decltype variants also fit in what I would call ugly category...
I think decltype can be used:
auto area = vd.size() * sizeof(decltype(vd)::value_type);
as you are using auto I assume C++11 is permitted.
Confirmed with g++ v4.7.2 and clang v3.3.
How about a simple helper function?
template <typename Container>
size_t value_size(const Container &)
{
return sizeof(typename Container::value_type);
}
[...]
vector<double> vd;
auto area = vd.size() * value_size(vd);
You could even overload the function so that it works with other containers such as arrays (of course, you would need to wrap size as well).
Ideally, the entire computation could be wrapped into a generic function:
template <typename Container>
size_t area(const Container &c)
{
return c.size() * sizeof(typename Container::value_type);
}
//possible overload for arrays (not sure it's the best implementation)
template <typename T, size_t N>
size_t area(const T (&arr)[N])
{
return sizeof(arr);
}
[...]
std::vector<double> vd;
auto vd_area = area(vd);
double arr[] = { 1., 2. };
auto arr_area = area(arr);
In C++11, you could use decltype(vd[0]):
auto area = vd.size()* sizeof (decltype(vd[0]));
But in the particular scenario, you could just write this:
auto area = vd.size()* sizeof (vd[0]);
Since the expression inside sizeof (and decltype too) will not be evaluated, both will work even if vd is
empty.

Generating permutations via templates

I'd like a function, or function object, that can generate a permutation of its inputs with the permutation specified at compile time. To be clear, I am not looking to generate all of the permutations, only a specific one. For instance, permute<1,4,3,2>( a, b, c, d ) would return (a,d,c,b). Obviously, it is straightforward to do this with a permutation of a specific length, e.g. 2, like this
#include <boost/tuple.hpp>
template< unsigned a, unsigned b>
struct permute {
template< class T >
boost::tuple< T, T > operator()( T ta, T tb ) {
boost::tuple< T, T > init = boost::make_tuple( ta, tb );
return boost::make_tuple( init.get< a >(), init.get< b >() );
}
};
But, how would I go about doing this for an arbitrary length permuation? Also, is there a cleaner way of writing the above code? Yes, the above code is not restricted to making permutations as permute<2,2>(a,b) is allowed, but I don't see that as a flaw. However, can it be restricted to only allowing actual permutations?
C++0x provides variadic templates, which you should be able to use to handle an arbitrary length permutation. They were added specifically because the current version of C++ doesn't have a clean way of dealing with this kind of problem.