I have this class template:
template<class... T>
class Test {
std::vector<TestCase*> test_cases;
public:
Test() {
// Here, for each T an instance should be added to test_cases.
test_cases.push_back((new T)...);
}
};
This works fine for one template argument, but for multiple arguments I get this error:
error: too many arguments to function call, expected 1, have 2
How can I use variadic templates with new this way? What is the correct syntax?
EDIT: I think my question wasn't quite clear. What I want is this:
Test<TestCase1, TestCase2, TestCase3>;
// The constructor will then be:
test_cases.push_back(new TestCase1);
test_cases.push_back(new TestCase2);
test_cases.push_back(new TestCase3);
My compiler is clang 163.7.1 with this flag: -std=c++0x.
vector::push_back expects one parameter so you can't expand the variadic template in the function call.
Also I added a template parameter for the base class (from which all other classes derive).
Here's something that compiles.
struct base{};
struct d0 : base{};
struct d1 : base{};
struct d2 : base{};
#include <vector>
// termination condition for helper function
template <class T>
void add(std::vector<T*>&) {
}
// helper function
template <class T, class Head, class... Tail>
void add(std::vector<T*>& v) {
v.push_back(new Head());
add<T, Tail...>(v);
}
template <class T, class ... U>
class test
{
std::vector<T*> vec;
public:
test() {
add<T, U...>(vec);
}
};
int main()
{
test<base, d0,d1,d2> t;
}
You can accomplish this, but it’s a bit roundabout since you write the expression directly. You need to call push_back once for each argument in the variadic template argument list.
How do you achieve this? Well, by calling a recursive function once for each template argument:
template <typename Base, typename T1, typename T2, typename... T>
void fill(std::vector<Base*>& vec) {
vec.push_back(new T1);
fill<Base, T2, T...>(vec);
}
template <typename Base, typename T1>
void fill(std::vector<Base*>& vec) {
vec.push_back(new T1);
}
Here we have two overloads of the fill function, one with a variadic template argument list and one without – this is the recursion base case. As long as there are still at least two template arguments, the first version gets called. If there is only a single argument left, the second argument is called instead.
Call it like this in the constructor:
fill<TestCase, T...>(test_cases);
Pack expansion can only happen in a select number of situations and doesn't work for arbitrary expressions or statements. However, since one of those situation is list-initialization and since the order of operations is defined for the brace initializers of list-initialization syntax, it's always possible to expand an arbitrary statement. To wit:
typedef std::initializer_list<int> expand;
expand { ( test_cases.push_back(new T), void(), 0 )... };
The void() trick is to suppress any invocation of an overloaded operator,. Completely irrelevant here but I have included it since it may be useful when refactoring the functionality in a macro:
#define EXPAND( exp ) \
std::initializer_list<int> { ( (exp), void(), 0 )... }
// No use of '...', it's in the macro body
EXPAND(( test_cases.push_back(new T) ));
On a related note, in this particular case you can use vector's initializer_list support by writing the constructor as follows
Test()
:test_cases{ new T ... }
{ }
Or by using assignment if for any reason you can't use constructor initializers
Test() {
test_cases = { new T ... };
}
Maybe you want a tuple inside your std::vector? Not sure if this is what you intended, but this compiles at least on my G++ 4.6.1 :D
#include <vector>
#include <utility>
#include <functional>
#include <string>
template<class... T>
class Test {
std::vector<std::tuple<T*...>> test_cases;
public:
Test() {
// Here, for each T an instance should be added to test_cases.
test_cases.push_back(std::tuple<T*...>((new T)...));
}
};
int main()
{
Test<int, float> foo;
Test<std::string, double> bar;
}
It strikes me you want a dynamic vector of any type (although not personally looking myself, I was told by a friend there was apparently something like this in the boost library), as opposed to a template vector.
A template vector is basically a vector that can assume any of one defined type (either all ints, or all doubles, or all floats but not ints and doubles and floats).
The reason there isn't a class like this conventionally is because each item takes up a different block size in memory (a char is a byte, an int could be 4 bytes etc etc), and it would take additional resources on look-up to know what to expect (normal storage is contiguous... which a vector is, given it is 'basically' an array).
If you're looking to build your own (I tried), you're looking at void * pointers, dynamic memory allocation and a whole host of headaches involving typecasting (I am unaware of any automated method to correctly typecast an item behind the scenes, but others might be able to chip in).
Related
Unlike function declarations with parameter packs, I've found that classes require the type for each argument in the angle brackets...
Component<IntegerPair, int, int> temp(40, 5);
...which seems redundant. Here's how I defined Component:
template<typename T, class... T_Args>
class Component
{
public:
Component(T_Args... args)
: m_data(args...)
{}
T m_data;
};
Is there a way to remove int, int from the above statement?
If so, is it ok to remove it?
Also, is my way of instantiation m_data safe? When using
std::forward<T_Args>(args)... my compiler told me I didn't have a
constructor that could convert all of the argument types.
One way is to make the constructor a template:
#include <utility>
struct IntegerPair {
IntegerPair(int, int) {}
};
template<typename T>
class Component
{
public:
template<typename... T_Args>
Component(T_Args&&... args)
: m_data(std::forward<T_Args>(args)...)
{}
T m_data;
};
int main()
{
Component<IntegerPair> c {1,2};
}
This is functionally equivalent to std::vector and its member function emplace_back. It's perfectly ok, IMO. The error messages are pretty cryptic, as usual in template constructs like this, but this can be mitigated with an appropriate static_assert.
template parameter deduction only work for function calls so the basic pattern to achieve what you want looks like this:
template<typename T, class... T_Args>
Component<T, T_Args...> makeComponent(T_Args&&... args) {
return Component<T, T_Args...>(std::forward<T_Args>(args)...);
}
Usage:
auto c = makeComponent<IntegerPair>(1, 1)
Consider the following contrived example of a templated array definition:
template <typename t, unsigned int n> class TBase
{
protected:
t m_Data[n];
//...
};
template <typename t, unsigned int n> class TDerived : public TBase<t, n>
{
TDerived()
{
}
};
I can specialize this type to provide a non-default constructor for an array of length 2 as follows:
template <typename t> class TDerived<t, 2> : public TBase<t, 2>
{
public:
TDerived(const t& x0, const t& x1)
{
m_Data[0] = x0;
m_Data[1] = x1;
}
};
int main()
{
TDerived<float, 2> Array2D_A(2.0f, 3.0f); //uses specialised constructor
TDerived<float, 3> Array3D_A; //uses default constructor
return 0;
}
Is there some other way I can create a class that has different constructor options constrained against template parameters at compile-time without the requirement for a complete class specialisation for each variation?
In other words, is there some way I can have specialised constructors in the TBase class without the need for the intermediary step of creating TDerived whilst preserving the functionality of TBase?
I think deriving your class from a base class is not relevant to the question here, that's a mere implementation detail. What you really seem to be after is if there's a way to partially specialize member functions, like the constructor. Do you want something like this?
template <typename T, int N> class Foo
{
Foo(); // general
template <typename U> Foo<U, 2>(); // specialized, NOT REAL CODE
};
This doesn't work. You always have to specialize the entire class. The reason is simple: You have to know the full type of the class first before you even know which member functions exist. Consider the following simple situation:
template <typename T> class Bar
{
void somefunction(const T&);
};
template <> class Bar<int>
{
double baz(char, int);
};
Now Bar<T>::somefunction() depends on T, but the function only exists when T is not int, because Bar<int> is an entirely different class.
Or consider even another specialization template <> class Bar<double> : public Zip {}; -- even the polymorphic nature of a class can be entirely different in a specialization!
So the only way you can provide specializations new declarations of members, including constructors, is by specializing the entire class. (You can specialize the definition of existing functions, see #Alf's answer.)
There are basically two options I see for this:
Use a variadic function for construction (ie. "..." notation), you can use the value n inside that function to get your arguments from the stack. However, the compiler will not check at compile time if the user provides the correct number of arguments.
Use some serious template magic to allow a call chaning initialization, that would look like this: vector(2.0f)(3.0f). You can actually build something that at least ensures the user does not provide too many arguments here. However tha mechanism is a little more involved, I can assemble an example if you want.
You can always specialize a member, e.g.
#include <stdio.h>
template< class Type >
struct Foo
{
void bar() const
{ printf( "Single's bar.\n" ); }
};
template<>
void Foo< double >::bar() const
{ printf( "double's bar.\n" ); }
int main()
{
Foo<int>().bar();
Foo<double>().bar();
}
But you want effectively different signatures, so it's not directly a case of specializing a member.
One way forward is then to declare a constructor with a single argument, of a type dependent on the template parameters.
Then you can specialize that, as you want.
Cheers & hth.,
Since constructor is a function, you need to fully specialize the containing class to address your specific problem. No way out.
However, functions cannot be partially specialized (in all compilers). So suppose if you know that you need n = 2 when t = int or double then following is one alternative.
template<>
TDerived<int,2>::TDerived()
{
//...
}
template<>
TDerived<double,2>::TDerived()
{
//...
}
and so on.
[Note: If you use MSVC, then I think it supports partial specialization; in that case you can try:
template<typename t>
TDerived<t,2>::TDerived()
{
//...
}
though, I am not sure enough for that.]
You could give the most common definitions in the non-specialized class and static_assert (BOOST_STATIC_ASSERT for non C++0x) on the array length. This could be considered a hack but is a simple solution to your problem and safe.
template<typename T, unsigned int n>
struct Foo {
Foo(const T& x) { static_assert(n == 1, "Mooh!"); }
Foo(const T& x1, const T& x2) { static_assert(n == 2, "Mooh!"); }
};
The "evil" way would be variadic arguments.
template<typename T, unsigned int n>
struct Foo {
Foo(...) {
va_list ap;
va_start(ap, n);
for(int j=0; j < n; ++j)
bork[j] = va_arg(ap, T);
va_end(ap);
}
};
Then there is also C++0x and the good old make_something trick which is more difficult then one would think.
template<typename... T, unsigned int n>
Foo<T, n> make_foo(T&&...) {
// figure out the common_type of the argument list
// to our Foo object with setters or as a friend straight to the internals
Foo< std::common_type< T... >::type, sizeof(T) > foo;
// recursive magic to pick the list apart and assign
// ...
return foo;
}
If I have,
template<typename T1, typename T2, int N>
class X {};
Is there any way, that I can know class X has 3 template arguments ?
Use case in brief: There are two library classes ptr<T> (for normal pointer) and ptr_arr<T,N> (for pointer to array). These two are interacting with another class in following way:
template<typename T>
void Clear(const T &obj)
{
if(T::Args == 1) destroy(obj);
else destroy_arr(obj);
}
So, I thought if we have some handy way of knowing the number of parameters, it would make it easy. However, I learn that I need to change my business logic as there cannot be such way.
There is no standard way to do this (unless you use variadic sizeof(Args...) in C++0x) but that's beside the point -- the question is wrong.
Use overload resolution.
template <typename T>
void clear (ptr<T> & obj) {
destroy (obj);
}
template <typename T, int N>
void clear (ptr_arr<T,N> & obj) {
destroy_arr (obj);
}
You can use the mpl::template_arity (undocumented)
http://www.boost.org/doc/libs/1_40_0/boost/mpl/aux_/template_arity.hpp
There is no way to do this. Imagine the amount of overloads.
template<int> struct A;
template<bool> struct B;
template<char> struct C;
template<typename> struct D;
template<D<int>*> struct E;
template<D<bool>*> struct F;
template<typename, int> struct G;
// ...
For each of that, you would need a different template to accept them. You cannot even use C++0x's variadic templates, because template parameter packs only work on one parameter form and type (for example, int... only works for a parameter pack full of integers).
I have a bunch of overloaded functions that operate on certain data types such as int, double and strings. Most of these functions perform the same action, where only a specific set of data types are allowed. That means I cannot create a simple generic template function as I lose type safety (and potentially incurring a run-time problem for validation within the function).
Is it possible to create a "semi-generic compile time type safe function"? If so, how? If not, is this something that will come up in C++0x?
An (non-valid) idea;
template <typename T, restrict: int, std::string >
void foo(T bar);
...
foo((int)0); // OK
foo((std::string)"foobar"); // OK
foo((double)0.0); // Compile Error
Note: I realize I could create a class that has overloaded constructors and assignment operators and pass a variable of that class instead to the function.
Use sfinae
template<typename> struct restrict { };
template<> struct restrict<string> { typedef void type; };
template<> struct restrict<int> { typedef void type; };
template <typename T>
typename restrict<T>::type foo(T bar);
That foo will only be able to accept string or int for T. No hard compile time error occurs if you call foo(0.f), but rather if there is another function that accepts the argument, that one is taken instead.
You may create a "private" templatized function that is never exposed to the outside, and call it from your "safe" overloads.
By the way, usually there's the problem with exposing directly the templatized version: if the passed type isn't ok for it, a compilation error will be issued (unless you know your algorithm may expose subtle bugs with some data types).
You could probably work with templates specializations for the "restricted" types you want to allow. For all other types, you don't provide a template specialization so the generic "basic" template would be used. There you could use something like BOOST_STATIC_ASSERT to throw a compile error.
Here some pseudo-code to clarify my idea:
template <typename T>
void foo(T bar) {BOOST_STATIC_ASSERT(FALSE);}
template<> // specialized for double
void foo(double bar) {do_something_useful(bar);};
Perhaps a bit ugly solution, but functors could be an option:
class foo {
void operator()(double); // disable double type
public:
template<typename T>
void operator ()(T bar) {
// do something
}
};
void test() {
foo()(3); // compiles
foo()(2.3); // error
}
Edit: I inversed my solution
class foo {
template<typename T>
void operator ()(T bar, void* dummy) {
// do something
}
public:
// `int` is allowed
void operator ()(int i) {
operator ()(i, 0);
}
};
foo()(2.3); // unfortunately, compiles
foo()(3); // compiles
foo()("hi"); // error
To list an arbitrary selection of types I suppose you could use a typelist. E.g see the last part of my earlier answer.
The usage might be something like:
//TODO: enhance typelist declarations to hide the recursiveness
typedef t_list<std::string, t_list<int> > good_for_foo;
template <class T>
typename boost::enable_if<in_type_list<T, good_for_foo> >::type foo(T t);
Is there a way to have the compile deduce the template parameter automatically?
template<class T>
struct TestA
{
TestA(T v) {}
};
template<class T>
void TestB(T v)
{
}
int main()
{
TestB (5);
}
Test B works fine, however when i change it to TestA it will not compile with the error " use of class template requires template argument list"
No, there isn't. Class templates are never deduced. The usual pattern is to have a make_ free function:
template<class T> TestA<T> make_TestA(T v)
{
return TestA<T>(v);
}
See std::pair and std::make_pair, for example.
In C++0x you will be able to do
auto someVariable = make_TestA(5);
to avoid having to specify the type for local variables.
Sunlight is right, but if I may ask you a question: is that really a problem in your code. I mean:
TestA(5);
Would become
TestA<int>(5);
As long as it's only one template argument, it's not that bad, IMHO. It's not like you can get around typing the type once in most cases.