I am trying to store the parameter pack of lvalue references of a variadic template for later use.
I have the following working for now.
template <typename... Ts>
class Foo {
private:
std::tuple<Ts...> m_args;
public:
template<typename... Args>
Foo(Args&&... args) : m_args(std::make_tuple(std::forward<Args>(args)...))
{
}
};
int main() {
int x = 10;
int y = 20;
Foo<int, int> foo(x, y);
}
However, I would like to store the parameter pack as a reference so that I can access the same object later.
I am not sure how I can do that. Any help would be appreciated.
The best I can imagine, is the use of std::forward_as_tuple.
Unfortunately I don't see a way to use it with perfect forwarding: if you want register values in a tuple inside a class, you have to decide the type of the tuple one time for all.
The best I can imagine is a tuple of const references; something as follows
template <typename ... Ts>
class Foo
{
private:
std::tuple<Ts const & ...> m_args;
public:
Foo (Ts const & ... as) : m_args{std::forward_as_tuple(as...)}
{ }
};
I hope isn't necessary remember you how dangling references can be dangerous for a solution based on a tuple of references.
Related
I would like to check if there exist a member function with signature fit to a parameter pack. I began with the known SFINAE concept, while trying to extend it for considering also a parameters pack. But at this point I found that I don't know how to do it.
I try to do something like this:
// Note: T object may have several functions with the name foo, but with different signatures.
// a function foo also can be a template one with variadic parameters pack.
template<typename T, typename...Args>
class HAS_FUNCTION_FOO
{
template<typename U>
static bool test(decltype(&U::foo));
template<typename U>
static float test(...);
public:
static constexpr bool value = std::is_integral<decltype(test<T>(Args...))>::value;
//-------------------------------------------------------------^^^^^^^^^
// how to do it?
};
I would like to use it for declaring specific object at compile time - something like this:
class Bar
{
public:
template<typename T, typename...Args>
void doSomthing(T* p, Args&&...parameters)
{
// get correct object type:
// if T has a function called foo with parameters fits for pack, then declare A, o.w declare B.
using ObjType = typename std::conditional<HAS_FUNCTION_FOO<T, Args>::value, A, B>::type;
// compute
ObjType::doSomthing(p, std::forward<Args>(parameters)...);
}
private:
struct A
{
template<typename T, typename...Args>
static void doSomthing(T* p, Args&&...parameters)
{
p->foo(std::forward<Args>(parameters)...);
}
};
struct B
{
template<typename T, typename...Args>
static void doSomthing(T* p, Args&&...parameters)
{
// do something else
}
};
};
Something like this, perhaps:
template<typename T, typename...Args>
class HAS_FUNCTION_FOO
{
template <typename U>
static std::true_type test(
typename std::enable_if<sizeof(
decltype(std::declval<U>().foo(std::declval<Args>()...))*) != 0>::type*
);
template <typename U>
static std::false_type test(...);
public:
static constexpr bool value = decltype(test<T>(nullptr))::value;
};
Demo
I have methods with the following signature:
void DoStuff(int i);
void DoStuff(int i, k);
void DoStuff(int i, int k, int l);
I have a method from where I would like to call the DoStuff methods as follows:
void CallDoStuff(const std::vector<int>& vElements) {
// What magic is supposed to happen here to make vElements an expandable pack?
DoStuff(vElemets...);
}
Is there any chance to achieve this?
Is using std::index_sequence the right way? If yes, could you please provide me a simple example how to apply this to my problem?
The problem is that, from a std::vector, you can't -- compile time -- extract the size() value.
So you can obtain what you want only if you pass, as a compile-time known value, to CallDoStuff() the number of elements that you want to use from the vector.
You can pass it as, by example, a template value.
Using an helper function, you can write something as follows
template <std::size_t ... Is>
void CallDoStuff (std::vector<int> const & vElements,
std::index_sequence<Is...> const &)
{ DoStuff(vElements[Is]...); }
template <std::size_t N>
void CallDoStuff (std::vector<int> const & vElements)
{ CallDoStuff(vElements, std::make_index_sequence<N>{}); }
The call could be something as
CallDoStuff<5u>(v);
If you can use a std::array, instead of std::vector, the answer is different: you can extract the size() from the type itself, so
template <std::size_t N, std::size_t ... Is>
void CallDoStuff (std::array<int, N> const & vElements,
std::index_sequence<Is...> const &)
{ DoStuff(vElements[Is]...); }
template <std::size_t N>
void CallDoStuff (std::array<int, N> const & vElements)
{ CallDoStuff(vElements, std::make_index_sequence<N>{}); }
that is callable without explicating N as follows
std::array<int, 5u> arr { 2, 3, 5, 7, 11 };
CallDoStuff(arr); // no more <5u>
End note: observe that std::make_index_sequence and std::index_sequence are available only starting from C++14. In C++11 you have to substitute them in some way.
It's possible, as long as you provide an upper bound to the number of arguments.
Using Xeo's implementation of std::index_sequence for C++11:
template <unsigned... Idx>
void trampoline(const std::vector<int>& vElements, seq<Idx...>) {
return DoStuff(vElements[Idx]...);
}
template <std::size_t Arity>
void trampoline(const std::vector<int>& vElements) {
return trampoline(vElements, typename gen_seq<Arity>::seq{});
}
template <unsigned... Idx>
void CallDoStuff(const std::vector<int>& vElements, seq<Idx...>) {
using trampoline_t = void (*)(const std::vector<int>&);
constexpr trampoline_t trampolines[]{
trampoline<Idx>...
};
trampolines[vElements.size()](vElements);
}
template <std::size_t Max>
void CallDoStuff(const std::vector<int>& vElements) {
assert(vElements.size() <= Max);
return CallDoStuff(vElements, typename gen_seq<Max + 1>::seq{});
}
See it live on Wandbox
This can't be done, a template method call is bound at compile time but a std::vector doesn't know how many items it contains until runtime so there's no way to mix the two concepts.
DoStuff(vElemets...);
Here the compiler should choose the correct implementation according to how many elements vElements has. You see the flaw in this kind of thinking since std::vector is just an object that could contain any amount of items at point of invocation.
Unlike the class template arguments, which have to be specified by the user of the template, the function template arguments are deduced by the compiler. Therefore, a natural question arises: why might one want to specify default function template arguments?
One usage I can come up with is when we want to force some of the function template arguments without needing to specify all of them. However, this seems to be a corner case. Are there other cases?
This might be a partial answer. One use I thought of is when we have a template parameter that does not appear as type in the function's parameter list and thus cannot be deduced. Providing a default argument for that template parameter might be very reasonable. The above comment by n.m. provides a good example of this usage.
Try to convert below func into the constructor( they dont have return type).
template<class T>
typename std::enable_if< std::is_fundamental<T>::value >::type func(T p_arg){}
template<class T>
typename std::enable_if< !std::is_fundamental<T>::value >::type func(T const &p_arg){}
Its pretty easy with default function template arguments.
Example:
template <typename Y, typename Y, int Z>
class Do{};
X,Y,Z are template parameters.
A user can use this like:
Do<int,int,1> doit;
While using a class template there is no way that template parameters get deduced from a function argument.
You call something "default" arguments...
template <typename Y, typename Y, int Z=9>
class Do{};
Here Z is defaulted to 9 if nothing was given from the using code like:
Do<int,int> doit;
And if your template arguments can be deduced from function arguments a user maybe want a special template instance to be used like:
template <typename T>
void func( const T&);
template<>
void func( const int& )
{
std::cout << "int in use" << std::endl;
}
template<>
void func( const double&)
{
std::cout << "double in use" << std::endl;
}
int main()
{
func(3.4); // calls double
func<int>(3.4); //calls int
}
I have a template class TC who's constructor takes parameters who's values are dependent on, as well as being of type Tn.
So, I want to create a helper template function htf that will call the same functions of a Tn object to generate a TC for a set of types X0 to Xn. The helper function takes only one parameter from that set. Is it possible, perhaps with variadic templates, to write the function once for the set of types, instead of having to write the same function over and over again for each type?
Now, I could just use a template to allow all types, but I don't want that as there may be another function with the same name written for a specific type later that's not based on this TC. And, IIRC I think SFINAE works with member functions, not pure functions.
This is just an idea in my head at the moment, that's why the question is very general. However, here is roughly the code I'm thinking of, simplified, in an more concrete and in an over generalized fashion:
struct X0
{
int value;
int& fn() { return value; }
};
struct X1
{
double value;
double& fn() { return value; }
};
struct X2
{
float value;
float& fn() { return value; }
};
struct Y0 // don't accept this class in helper function
{
int value;
int& fn() { return value; }
};
template<typename T1, typename Tn>
class TC
{
T1* m_pT1;
Tn* m_pTn;
TC(T1* pT1, Tn* pTn) : m_pT1(pT1), m_pTn(pTn) {}
friend TC htf(Tn& tn);
public:
~TC() {}
};
// concrete functions:
TC<int, X0> htf(C0& x) { return TC<int, X0>(&x.fn(), &x); }
TC<double, X1> htf(C1& x) { return TC<double, X1>(&x.fn(), &x); }
TC<float, X2> htf(C2& x) { return TC<float, X2>(&x.fn(), &x); }
// or in an over generalized template function but it'll accept
// Y0 and others which I don't want:
template<typename X>
auto htf(X& x) -> TC<decltype(x.fn()), X>
{
return TC<decltype(x.fn()), X>(&x.fn(), &x);
}
So the htf function that I want is to work for classes X0, X1, and X2, but not Y0. However, I don't want it to interfere with any other function called htf that takes a parameter of type Y0, or any other type for that matter.
Additional
Is it possible to make it so that the collection of accepted classes can also include template classes taking an specified (or unspecified) number of parameters?
Write a function that is only enabled when a trait is true, then specialize it for all the desired types.
template<typename T>
struct enable_htf : std::false_type { };
template<>
struct enable_htf<X0> : std::true_type { };
template<>
struct enable_htf<X1> : std::true_type { };
// etc.
template<typename T, bool enable = enable_htf<T>::value>
struct htf_helper { };
template<typename T>
struct htf_helper<T, true>
{
using type = TC<decltype(std::declval<T&>().fn()), T>;
};
template<typename X>
typename htf_helper<X>::type
htf(X& x)
{
return { &x.fn(), &x };
}
But it seems you want something like this instead:
template<typename Needle, typename... Haystack>
struct is_one_of;
template<typename Needle, typename Head, typename... Tail>
struct is_one_of<Needle, Head, Tail...>
: conditional<is_same<Needle, Head>::value, true_type,
is_one_of<Needle, Tail...>>::type
{ };
template<typename Needle>
struct is_one_of<Needle> : false_type
{ };
template<typename X,
typename Requires = typename enable_if<is_one_of<X, X0, X1, X2>::value>::type>
auto
htf(X& x) -> TC<decltype(x.fn()), X>
{
return { &x.fn(), &x };
}
But personally I don't consider that clearer, even if is_one_of is reusable elsewhere.
This is an even more simplified version of my original question, but it relates to enabling a template function based on the type passed to it being part of a list of accepted types.
class A{};
class B{};
class C{};
class D{};
class collection1 : A, B, C {};
class collection2 : D {};
template<typename X>
typename std::enable_if<std::is_base_of<X, collection1>::value, X>::type fn(X x)
{
return X();
}
Then the following would work appropriately:
fn(A()); // works
fn(B()); // works
fn(C()); // works
fn(D()); // compile time failure
Having a 2nd function like this:
template<typename X>
typename std::enable_if<std::is_base_of<X, collection2>::value, X>::type fn(X x)
{
return X();
}
Would result in:
fn(A()); // works
fn(B()); // works
fn(C()); // works
fn(D()); // works
Using this method, I can enable function fn to work with types I want and not others and I can write the list with ease. Also, this should be faster than iterating through a list of variadic template parameters.
Thanks Jonathan Wakely, you helped a lot in my thought process. I just thought that this is simpler and can be made even clearer if I use a helper template which would encapsulate the enable_if clause which would be good as I have many other functions that would require this.
Additional
Looks like this answer isn't good enough as I need to be able to determine if a template class is in the collection I'm looking for.
I'm building a large project on Debian 6.0.6 (with gcc 4.4.5) that was initially built in Microsoft VS (2008, I think).
What seems to be the problem is that when I declare a member as
typedef typename std::set<T>::iterator iterator, and then later use this iterator, gcc appears to interpret this as (const T*).
The part of the class containing the typename designation:
template <class entityType>
class entityArray
{
private: std::set<entityType> m_array;
public: typedef typename std::set<entityType>::iterator iterator;
...
public:
entityType* At( const char* name);
...
};
plus a few other classes that are needed for the discussion:
class entity
{
private:
entity* m_parent;
int m_ncid;
std::string m_name;
public:
entity () { m_ncid = 0; m_parent = NULL;}
virtual ~entity () {};
...
};
class attribute : public entity
{
public:
attribute(){};
virtual ~attribute(){};
};
class var : public entity
{
private:
entityArray<attribute> m_atts;
public:
var(){}
virtual ~var(){}
...
};
class dim : public entity
{
public:
dim() {};
virtual ~dim() {};
};
class group : public entity
{
private:
entityArray<var> m_vars;
entityArray<dim> m_dims;
...
public:
dim* DimAt( const char* dimname ) { return m_dims.At(dimname);}
};
Now an iterator is initialized through a call to the function DimAt which in turn calls At. The At function in the first class is defined as:
template <class entityType>
entityType* entityArray<entityType>::At( const char* name )
{
entityType dummy;
iterator iter;
entityType* ptr;
... define dummy ...
iter = m_array.find( dummy );
ptr = (iter != m_array.end()) ? &(*iter) : NULL;
return ptr;
}
Compiling the above produces
error: invalid conversion from const dim* to dim*., referring to &(*iter).
I realize that typename is required for declaring iterator, since the type is a dependent and qualified name, but I don't see why this substitution (const *) is being performed by the compiler. I would appreciate any help that you could provide. Thanks!
This has absolutely nothing to do with typename.
The standard allows std::set<T>::iterator and std::set<T>::const_iterator to be the same type, and with GCC the types are the same.
The reason is that modifying an element of a std::set e.g. by *iter = val might invalidate the ordering of the set elements, breaking the invariant that the elements of the set are always in order. By making the iterator type a constant iterator instead of a mutable iterator it's not possible to alter the element, preventing you from corrupting the set's ordering.
So with GCC's implementation, when you dereference the iterator using *iter you get a const entitType& and when you take its address using &*iter you get a const entityType*