I am not really sure if there's such a feature in C++, and if there is I can't seem to make it work, so I decided to ask. Can I have a template template non-type parameter. Something like this:
template<template<int> class A, int num>
class C
{
private:
A<num> obj;
};
My main issue is that I want to have a class C that accepts 2 classes as template parameters. Both of these classes specialize over a non-type parameter - say A<5>, B<5> and I want to pass them to class C which accepts two classes as template parameters. I need to make sure however that both of these classes specialize over the same non-type parameter - for example A<3>, B<4> shouldn't be allowed as arguments to class C.
A similar approach would be to do something like this:
template<int I>
class A {};
template<int I>
class B {};
// Forward declaration.
template<typename T, typename U>
class C;
template<template<int> class TA, template<int> class TB, int I, int J>
class C<TA<I>, TB<J>> {
// J exists only to make sure integer parameters match.
static_assert((I == J), "Template parameters' integer parameters are mismatched.");
private:
TA<I> objA;
TB<I> objB;
public:
// ...
};
// ...
C<A<4>, B<4>> ca4b4; // Valid.
C<A<4>, B<16>> ca4b16; // Static assert fails.
This will allow you to guarantee that both containers have the same integer parameter, and emit a readable error message if they don't.
Edit: Note that if you don't use two separate integer parameters and manually check for equality, attempting to create an instance with mismatching template template parameters will give off a less understandable "incomplete type" error message.
template<template<int> class TA, template<int> class TB, int I>
class C<TA<I>, TB<I>> {
// ...
};
// ...
C<A<4>, B<16>> ca4b16; // Oops.
/* Error messages:
* GCC:
* error: aggregate 'C<A<4>, B<16> > ca4b16' has incomplete type and cannot be defined
* C<A<4>, B<16>> ca4b16;
* ^
* MSVC:
* error C2079: 'ca4b16' uses undefined class 'C<T, U>'
* with
* [
* T=A<4>,
* U=B<16>
* ]
*/
This is because the actual definition will only be able to catch instances where both parameters have the same integer parameter, and any usage with mismatching integer parameters will instead fall back on the forward declaration, which is incomplete. Using two separate integer parameters, then manually checking for equality, allows us to catch bad instantiations instead of letting them fall back on the declaration, so we can convert that generic error into something that actually tells you what the problem is.
You may want to simplify your code with a "makeC":
#include <iostream>
template <template<int> class A, template<int> class B, int N>
class C {
A<N> a;
B<N> b;
};
using namespace std;
template <template<int> class A, template<int> class B, int N>
C<A,B,N> makeC(A<N> a, B<N> b) {
return C<A, B, N>{};
}
template<int N>
class AImpl {
};
template<int N>
class BImpl {
};
int main() {
auto c = makeC(AImpl<2>{}, BImpl<2>{});
//auto error = makeC(AImpl<1>{}, BImpl<2>{});
return 0;
}
My bad, after some tinkering I managed to call it right. The issue was I was calling C<A<5>> and i needed to obviously call C<A, 5>. Here's an example of how I made the whole thing work just in case if anybody ever needs it:
template<int a, int b, int c>
class Anac
{
public:
void print()
{
std::cout << "Anac: " << a << " " << b << " " << c << "\n";
}
};
template<int a, int b, int c>
class Mamut
{
public:
void print()
{
std::cout << "Mamut: " << a << " " << b << " " << c << "\n";
}
};
template <class C>
class R
{
};
template< template<int, int, int> class A, template<int, int, int> class B, int a, int b, int c>
class gm
{
private:
A<a,b,c> p1;
B<a,b,c> p2;
public:
void print()
{
p1.print();
p2.print();
}
};
int main()
{
gm<Anac, Mamut, 3, 4, 5> game;
game.print();
std::cin.ignore();
return 0;
}
Related
I have a class and need to validate that it's function calls are being called w/ the right parameters. The function signature is always the same (sans 1 argument type). So, naturally I went for a templated approach. So generally the validation policy would have a template parameter per data type it could handle:
using P = Policy<int, double, UserDefined>
Or something of that ilk.
I got it to compile, but the caveat is that if double and int (or anything a double can convert to actually) are both template parameters, the double will be implicitly converted.
The policy looks like this:
template <typename... T>
class BasicValidationPolicy { };
template <>
class BasicValidationPolicy<>
{
public:
void RegisterSetHandler();
};
template <typename T, typename... Rest>
class BasicValidationPolicy<T, Rest...> : public BasicValidationPolicy<Rest...>
{
public:
using SetHandler = std::function<void(int, T)>;
void RegisterSetHandler(const SetHandler& handler)
{
m_setHandler = handler;
}
void Set(int n, const T& val) {
if (m_setHandler) {
m_setHandler(n, val);
}
}
private:
SetHandler m_setHandler{nullptr};
};
The class that uses it...
template <typename ValidatorPolicy>
class MyClass : public ValidatorPolicy {
public:
void OnSetInt(int n, int64_t v)
{
ValidatorPolicy::Set(n, v);
}
void OnSetDouble(int n, double d)
{
ValidatorPolicy::Set(n, d);
}
};
Usage:
int main()
{
using Policy = BasicValidationPolicy<int64_t, double>; // doesn't work
MyClass<Policy> m;
m.Policy::RegisterSetHandler([](int i, double value) {
// by this point value is an int64_t
std::cout << "Got double " << i << ", " << value << "\n";
});
double d{35.2135};
m.OnSetDouble(1, d);
}
To boot, doing this does work
using Policy = BasicValidationPolicy<double, int64_t>;
So I guess I'm missing something about the template deduction. Looks like it tries to match double against std::int64_t says "meh, good enough", and moves on. Nice to know a way around it (kind of) but that looks like it would be very tricky to maintain.
It's complicated...
First of all: you have a recursive template class, BasicValidationPolicy, where you define two methods and you want that all methods, for all recursion steps of the class, are available.
Unfortunately, the definition of the methods in the derived classes hide the method in base classes.
To un-hide the inherited methods, you have to explicitly add a pair of using
using BasicValidationPolicy<Rest...>::Set;
using BasicValidationPolicy<Rest...>::RegisterSetHandler;
At this point, the code doesn't compile because you need a Set() and a RegisterSetHandler() in the ground case class. You have declared a dummy RegisterSetHandler() but not a dummy Set(). You have to add one, so the ground case become
template <>
class BasicValidationPolicy<>
{
public:
void RegisterSetHandler();
void Set();
};
Now your MyClass<Policy> object expose two RegisterSetHandler() methods (before only one): one receiving a std::function<void(int, std::int64_t)>, the other (before hidden) receiving a std::function<void(int, double)>.
But when you pass a lambda, you have a chicken-and-egg problem: the lambda can be converted to a std::function but isn't a std::function. So can't be used to deduce the template parameters of std::function because the types are to be known before to deduce them.
A possible solution is impose a lambda/std::function conversion in the call
// ..........................VVVVVVVVVVVVVV
m.Policy::RegisterSetHandler(std::function{[](int i, double value) {
// by this point value is an int64_t
std::cout << "Got double " << i << ", " << value << "\n";
}});
// ...........................^
using also the template deduction guides introduced in C++17.
So your code become
#include <iostream>
#include <functional>
template <typename... T>
class BasicValidationPolicy { };
template <>
class BasicValidationPolicy<>
{
public:
void RegisterSetHandler();
void Set();
};
template <typename T, typename... Rest>
class BasicValidationPolicy<T, Rest...> : public BasicValidationPolicy<Rest...>
{
public:
using SetHandler = std::function<void(int, T)>;
using BasicValidationPolicy<Rest...>::Set;
using BasicValidationPolicy<Rest...>::RegisterSetHandler;
void RegisterSetHandler(const SetHandler& handler)
{
m_setHandler = handler;
}
void Set(int n, const T& val) {
if (m_setHandler) {
m_setHandler(n, val);
}
}
private:
SetHandler m_setHandler{nullptr};
};
template <typename ValidatorPolicy>
class MyClass : public ValidatorPolicy {
public:
void OnSetInt(int n, int64_t v)
{
ValidatorPolicy::Set(n, v);
}
void OnSetDouble(int n, double d)
{
ValidatorPolicy::Set(n, d);
}
};
int main ()
{
using Policy = BasicValidationPolicy<int64_t, double>; // doesn't work
MyClass<Policy> m;
m.Policy::RegisterSetHandler(std::function{[](int i, double value) {
std::cout << "Got double " << i << ", " << value << "\n";
}});
double d{35.2135};
m.OnSetDouble(1, d);
}
There's a small alternative to the recursive definition that might be easier to work with...
template<typename T>
class ValidationPolicy {
// Set/Register/etc
};
template <typename... Ts>
class BasicValidationPolicy : public ValidationPolicy<Ts>... {
public:
using ValidationPolicy<Ts>::Set...;
using ValidationPolicy<Ts>::RegisterSetHandler...;
};
This can have some impacts on compile time and other aspects of development, though most likely relatively minor. For instance, if you have dozens of classes used in hundreds of different policy combinations in your app, the recursive definition will lead to many more distinct types and larger binaries to support that. For example, in the recursive definition BasicValidationPolicy<T1, T2, T3> and BasicValidationPolicy<T3, T2, T1> being used would generate 7 distinct types in a hierarchy (the empty one is shared in both expansions). The same thing in the flatter hierarchy would be 5 distinct types - one for each of T1, T2, T3 and one for each combination. Adding in BasicValidationPolicy<T2, T3, T1> would add 3 more types recursively but 1 more type in the flat form.
The answer from #max66 isn't wrong, just something else to think about.
I am trying to make a generic factory method in C++, that can create an instance of one of many (but finite number of) objects. Each of the objects require different types of parameters to construct so I want the method to somehow infer the desired type and not want to have the user specify it explicitly.
Here's some code to illustrate what I'm trying to do:
#include <iostream>
using namespace std;
class A {
public:
A(int x, int y) {
cout << "A(" << x << ", " << y << ")\n";
}
};
class B {
public:
B(float a, float b) {
cout << "B(" << a << ", " << b << ")\n";
}
};
template<typename T, typename... Ts>
T * Make(Ts... vs) {
puts(__PRETTY_FUNCTION__); // __FUNCSIG__ or __PRETTY_FUNCTION__
return new T{ vs... };
}
Now the code in, say, main function can create objects of type A * and B * by invoking Make like this:
A *a = Make<A>(3, 4);
B *b = Make<B>(3.14f, 6.28f);
Is there a way I can extend this code to enable other functions to call Make without having to explicitly specify whether they want an instance of A * or B * ? For example,
A * a = Make(3, 4); // (int, int)
B * b = Make(3.14f, 6.28f); // (float, float)
I understand function templates get instantiated using argument type deduction and return type is not involved in this. However, the compiler will not do any type conversions. So Make(int, int) is definitely a different instance from Make(float, float) and I want to be able to leverage this to map the function definition to the right return type.
Here's what I tried:
defining an explicit instantiation
template A * Make(int x, int y);
defining a specialization
template<>
A * Make<A, int, int>(int x, int y);
Both didn't work as expected. Any ideas on how this can be achieved ?
I wrote a Maker helper template that registers which classes are allowed, although I don't exactly know how to disable the base template:
template <typename... Ts>
struct Maker {
using type = void;
};
template <>
struct Maker<int, int> {
using type = A;
};
template <>
struct Maker<float, float> {
using type = B;
};
template<typename... Ts, typename T=typename Maker<Ts...>::type>
T * Make(Ts... vs) {
puts(__PRETTY_FUNCTION__); // __FUNCSIG__ or __PRETTY_FUNCTION__
return new T{ vs... };
}
int main() {
A * a = Make(3, 4); // (int, int)
B * b = Make(3.14f, 6.28f); // (float, float)
}
You might give needed information to the factory, set of class to construct, and needed arguments(*).
(*): (Note: if your classes has correct properties, you might even detect constructor's arguments automatically with magic_get.
template <typename ... Sigs> struct Maker : Maker<Sigs>...
{
using Maker<Sigs>::operator ()...;
// Do we want to accept conversions or not in non ambiguous cases ?
//template <typename ... Ts> operator()(Ts/*&&*/...) const = delete;
};
template <class C, typename ... Args> struct Maker<C(Args...)>
{
C operator()(Args... args) const {
puts(__PRETTY_FUNCTION__); // __FUNCSIG__ or __PRETTY_FUNCTION__
return C(std::forward<Args>(args)...); // not {} to avoid initializer_list constructor
}
};
And then the factory instance:
constexpr Maker<A(int, int), B(float, float)> Make{};
With usage:
A a = Make(3, 4); // (int, int)
B b = Make(3.14f, 6.28f); // (float, float)
Demo
I have a class template Function that takes a unsigned integer as a template argument, for the number of inputs. This template overloads operator() so the Function can be evaluated for a set of given inputs.
Usually, one of the prototypes for this member would be operator()(double, ...). However, if the template argument is 0, then that prototype wouldn't work, as it requires at least one argument.
template <unsigned Arity>
struct Function {
void operator () (double, ...);
};
Normally, I'd just write a template specialization, but there would be a lot of redundant code since there are a lot of other member functions. Again, normally, I'd make a base class containing the redundant code for the main class definition and the specialization to inherit from.
struct FunctionBase {
// Common code
Function operator + (Function const &) const; // ?
};
template <unsigned Arity>
struct Function : FunctionBase { /* etc */ };
Unfortunately, I'm unsure how to go about doing this, since for example operator+ is meant to return a Function. But how can it do this if Function is only defined later on? Function inherits from the base class, and by this design operator+ is in the base class...
It could return an instance of the base class, but then we need a way to convert that instance to an instance of Function, and I know of no way to do this without copying the first instance's data, which is very expensive in terms of performance.
How can I accomplish this?
The question is quite difficult to answer for it's far from being clear.
Below two possibile alternatives that try to address your issues:
If you want to go ahead with Arity template parameter, you can use sfinae'd operators to deal with Arity equal to 0:
#include<iostream>
template<int Arity>
struct Function {
template<int N = Arity>
std::enable_if_t<N == 0> operator()() {
std::cout << "arity == 0" << std::endl;
}
template<int N = Arity>
std::enable_if_t<N != 0> operator()(double, ...) {
std::cout << "arity != 0" << std::endl;
}
};
int main() {
Function<0> f1;
Function<2> f2;
f1();
f2(0., 42);
}
This way you no longer need to introduce a base class and all the related problems don't apply anymore.
If you mind changing approach instead, you can switch to the following pattern for your function object:
template<typename>
struct Function;
template<typename R, typename... A>
struct Function<R(A...)> {
R operator()(A... args) {
// ...
}
// ...
};
You can use it as it follows:
Function<void(int, char)> f;
If you want to have a fixed double as you first parameter for operator(), you can do this:
template<typename R, typename... A>
struct Function<R(double, A...)> {
R operator()(double d, A... args) {
// ...
}
// ...
};
And use it as it follows:
Function<void(double, int, char)> f1;
Function<void(double)> f1;
This will help at least dealing easily with empty parameter packs (note that sizeof...(A) will return you the number of submitted parameters in any case).
It follows a minimal, working example implementation:
#include<iostream>
template<typename>
struct Function;
template<typename R, typename... A>
struct Function<R(A...)> {
R operator()(A... args) {
int _[] = { 0, (std::cout << args << std::endl, 0)... };
(void)_;
}
template<typename... O>
Function<R(A..., O...)> operator+(Function<R(O...)>) {
return {};
}
// ...
};
int main() {
Function<void(int)> f1;
Function<void(double)> f2;
f1(42);
f2(0.);
(f1+f2)(3, .3);
}
From this question Why should I avoid std::enable_if in function signatures it seems I should be able to write
#include <type_traits>
#include <iostream>
enum Class {
Primary,
Secondary
};
template<Class C>
class Entity {
public:
template<typename Cls = C, typename Sec = Secondary, std::enable_if<std::is_same<Cls, Sec>::value>::type = 0>
void onlyLegalForSecondaryEntities() {
std::cout << "Works" << std::endl;
}
};
int main() {
Entity<Secondary> e;
e.onlyLegalForSecondaryEntities();
return 0;
}
But this fails compilation with error prog.cpp:13:7: note: template argument deduction/substitution failed
How do I get this code to compile?
Your use of Class for an enum is a horrible idea. Don't use language keywords with capitalization differences as type names.
C is a compile-time value of type Class. It is not a type.
typename Cls = C attempts to assign a value of type Class to a type. This is an error akin to saying "picking up a sad". sad is not a noun, it is not something you can pick up.
The easiest way to make your code compile is to delete onlyLegalForSecondaryEntities entirely, and all references to it.
In general, under the standard you cannot have a template method which is only valid when certain arguments are passed to the template class it exists within. Doing so makes your program ill formed, no diagnostic required.
This is close:
template<Class Cls = C,
std::enable_if_t< Cls == Secondary, int> =0
>
void onlyLegalForSecondaryEntities() {
std::cout << "Works" << std::endl;
}
except that even on Entity<Primary>, you can do .onlyLegalForSecondaryEntities<Secondary>().
If you don't want to permit this, I'd use CRTP.
template<bool b, class D>
struct empty_if_false {};
template<class D>
struct empty_if_false<true, D> {
D* self() { return static_cast<D*>(this); }
D const* self() const { return static_cast<D*>(this); }
void onlyLegalForSecondaryEntities() {
// use self() instead of this in this method to get at a this pointer
std::cout << "Works" << std::endl;
}
};
then:
template<Class C>
class Entity:public empty_if_false< C==Secondary, Entity<C> > {
to conditionally have the method.
I have the following problem:
Suppose I have some basic counter class Counter. And suppose we also have some sets of classes, that can be counted. Let's name some of them class CountedA and class CountedB.
Now, every class, which can be counted (such as CountedA and CountedB) has the following statically declared parts: one enum and one int part, that acts like a part of counted data.
For example, it's declaration could look the following way:
enum CountedType { A, B };
template <CountedType Type, int N>
class Counted { };
// Now we can declare 'CountedA' and 'CountedB'
typedef Counted<A, 25> CountedA;
typedef Counted<B, 7> CountedB;
Now, the declaration of the counter:
// C++0x variadic or simply bunch of 'typename XX' definitions for C++03
template <typename T0, typename T1, typename ...>
class Counter
{
// I don't know how to implement this
// for now!
int GetTotalN() { ... }
// Retrieve the corresponding type
// so that GetTypeAt<0> returns
// enum from 'T0'
template <int Pos>
CountedType GetTypeAt() { ... }
};
I want to be able to write something like:
class RealCounter : public Counter<CountedA, CountedB> { };
And use it the following way:
RealCounter counter;
int n = counter.GetTotalN();
CountedType type = counter.GetTypeAt<0>();
Now, I'm pretty sure that this can be done. But what's the best way of implementing it? (don't ask me why would I need such crazy kind of things :)
Does boost::mpl offer something for this case?
Thank you.
Small update:
In this particular example, GetTotalN() should return 25 + 7.
If we add, for example, typedef Counted<C, 2> CountedC, then the result for
RealCounter : public Counter<CountedA, CountedB, CountedC>
should become 25 + 7 + 2.
Here's C++03 code which works (for up to 10 template arguments). The main trick is giving class Counter a multiple inheritance, and passing objects of type Counter to function templates which must select a base class. The actual summation is done recursively.
Counter.hpp
enum CountedType { A, B };
template <CountedType Type, int N>
struct Counted {};
struct DummyCounted {};
template <int Pos, typename T>
struct IndexedType {};
template <unsigned int Terms>
struct PartialSum
{
template <typename CounterT>
static int getSum(const CounterT& ctr)
{ return PartialSum<Terms-1>::getSum(ctr) + ctr.template GetNAt<Terms>(); }
};
template <> struct PartialSum<0U>
{
template <typename CounterT>
static int getSum(const CounterT& ctr)
{ return ctr.template GetNAt<0>(); }
};
template <typename T0, typename T1=DummyCounted,
typename T2=DummyCounted, typename T3=DummyCounted,
typename T4=DummyCounted, typename T5=DummyCounted,
typename T6=DummyCounted, typename T7=DummyCounted,
typename T8=DummyCounted, typename T9=DummyCounted>
class Counter :
public IndexedType<0, T0>, public IndexedType<1, T1>,
public IndexedType<2, T2>, public IndexedType<3, T3>,
public IndexedType<4, T4>, public IndexedType<5, T5>,
public IndexedType<6, T6>, public IndexedType<7, T7>,
public IndexedType<8, T8>, public IndexedType<9, T9>
{
public:
static int GetTotalN() {
return PartialSum<9>().getSum( Counter() );
}
template <int Pos>
static CountedType GetTypeAt() { return _getTypeAt<Pos>( Counter() ); }
template <int Pos>
static int GetNAt() { return _getNAt<Pos>( Counter() ); }
private:
template <int Pos, CountedType Type, int N>
static CountedType _getTypeAt(const IndexedType<Pos, Counted<Type,N> >&)
{ return Type; }
template <int Pos, CountedType Type, int N>
static int _getNAt(const IndexedType<Pos, Counted<Type,N> >&)
{ return N; }
template <int Pos>
static int _getNAt(const IndexedType<Pos, DummyCounted>&)
{ return 0; }
};
Counter.cpp
#include "Counter.hpp"
#include <iostream>
typedef Counted<A, 25> CountedA;
typedef Counted<B, 7> CountedB;
class RealCounter : public Counter<CountedA, CountedB> {};
int main()
{
RealCounter counter;
int n = counter.GetTotalN();
CountedType type = counter.GetTypeAt<0>();
std::cout << "n is " << n
<< "\ntype check is " << (type == A) << std::endl;
return 0;
}
Output:
n is 32
type check is 1
That C++0x variadic template stuff looks interesting, but I haven't taken a good look at it yet. But I do think in C++0x, all this example's functions (except main of course) could be constexpr.
I'm not sure why you need to embed those parameters in the templates arguments and not simply in a constructor since they are all the same types for each "derived" CountedA/B types.
Anyways you can embed the resulting types into a std::tuple as shown in the link below (see Message class for an example). Then create a variadic template function similar to the applyTuple version in the link below that will add all your integer arguments and return the final result once all arguments have been unrolled. As for the returning of the enum value for the item in "Pos" simply call the get( tuple ).getEnum() or .value to get it.
How do I expand a tuple into variadic template function's arguments?