I have the need to have a template class. I want to pass the template a type and then two member variable pointers. The second pointer I want to be defaulted to NULL and thus optional. Is this possible and if so what is the syntax?
What I expected to be the syntax is
template<typename T, int T::*VALUE1, int T::*VALUE2 = NULL>
class Foo { ... }
However when I attempt to instantiate an instance of this class;
Foo<Bar, &Bar::var1> fooBar;
Though instantiating using the following works
Foo<Bar, &Bar::var1, &Bar::var2> fooBar
The error given (from g++ 4.4) is
error: could not convert template argument '0l' to 'int Bar::*'
Please note that I can not use c++11 and thus nullptr
This restriction has been in the language since the beginning of times. In C++98 you are not allowed to use 0 as non-type template argument for any template parameters of pointer type or pointer-to-member type. E.g. this is invalid
template <int *p> struct S {};
...
S<0> s1; // ERROR: `0` is not a valid argument for `int *` parameter
S<(int *) 0> s2; // ERROR: unacceptable address expression
In other words, in the original version of C++ language you were simply not allowed to pass null pointers as template parameters. It was deliberately blocked by the language authors. The opportunity to do so appeared only in C++11 with the introduction of nullptr.
Use nullptr:
struct Bar
{
int var1;
};
template<typename T, int T::*VALUE1, int T::*VALUE2 = nullptr>
struct Foo
{
};
int main()
{
Foo<Bar, &Bar::var1> fooBar;
return 0;
}
live example: https://ideone.com/2ICSBJ
As explained here , pointer to class members are used to provide indirect access to class members. Now for the declaration of object foobar1 needs a class template that takes one member of class bar.
Now your second call is completely different class template which wants to access two members of class Bar.
So you will have to define two different class templates say foo1 and foo2 for that purpose as shown below :
template<typename T, int T::*VALUE1>
class Foo1 { ... }
template<typename T, int T::*VALUE1, int T::*value2>
class Foo2 { ... }
And you will call these like this :
Foo1<Bar,&Bar::var1> foobar1;//use first class template Foo1
Foo2<Bar,&Bar::var1,&Bar::var2> foobar2;//use second class template Foo2
Related
I have a problem with inner classes in class templates. I have a template class (say: Matrix<T>), and a subclass (say: Matrix<T>::Row). Now I want to to write a function which operates on instances of the subclass (say: negate(Matrix<T>::Row &)). I tried to declare the function with template<class T> negate(typename Matrix<T>::Row &), but when I try to use it, the compiler tells me that it cannot find a match.
Here's an abstract example:
template<class T>
class A
{
public:
class B
{
};
};
template<class T>
void x(typename A<T>::B &)
{
}
int main()
{
A<int>::B b;
x(b); // doesn't work: Error: Could not find a match
// for x<T>(A<int>::B) needed in main().
x<int>(b); // works fine
}
Why does the compiler does not manage to find x in the first case? Is there a way to modify this that it works (without explicitly specifying the type int)?
(I also have similar problems where x is of the form template<class T, class S> void x(typename A<T>::B &, const S &);, whence I would really like not to be forced to explicitly name all types while doing the call.)
I have tried this with g++ 4.4.3, g++ 4.5.2, and Sun Studio 5.9, all give the same result. Thanks a lot in advance for anything helpful!
How should the compiler be able to deduce this? Imagine the following setup:
struct A { typedef int T; };
struct B { typedef int T; };
template <typename S> void foo(typename S::T);
Now when you say int x; foo(x);, there's no way to match this unambiguously.
The point is that you are not deducing a template parameter from a given class template, but rather just an arbitrary, free-standing type. The fact that that type was defined inside another class is not relevant for that.
That is non-deducible context. That is why the template argument cannot be deduced by the compiler.
Just imagine, you might have specialized A as follows:
template <>
struct A<SomeType>
{
typedef std::map <double, double> B;
};
Now this specialization has a nested type called B which is a typedef of std::map<double,double>.
So how would the compiler deduce the type SomeType, given that A<SomeType>::B is std::map<double, double>?
And in fact, there can be many such specializations, as such:
template <>
struct A<SomeOtherType>
{
typedef std::map <double, double> B;
};
Even this specialization has B as nested type.
Now if I say A<T>::B is std::map<double,double>, then can you say what T is? Is it SomeType? or SomeOtherType?
It would need to deduce the type T for the call to template function x, and template argument deduction is only allowed in a specific set of circumstances:
http://publib.boulder.ibm.com/infocenter/compbgpl/v9v111/index.jsp?topic=/com.ibm.xlcpp9.bg.doc/language_ref/template_argument_deduction.htm
A<T>::B
does not seem to be one of them :/
Please I want complete example of how to use Non-type template parameters pointer to object, I tried this code but it contains alot of errors
class Foo
{
public:
Foo()
{
}
};
template<typename T,Foo* foo>
class TFoo
{
public:
TFoo()
{
}
};
int main()
{
Foo foo;
TFoo<float,&foo> tfoo;
}
Template parameters are to be evaluated in compile-time to instantiate a template, but the value of &foo is known only in run-time. That is your problem.
Probably, you should use different architecture. May be you could pass Foo* as a non-template parameter to your constructor. (I can't even imagine a purpose, for which a pointer as a template parameter could be useful).
I have a template class
template<int N>
class xyz{
some code ....
};
if I do not use N inside the class, then all objects of this class should be compatible irrespective of the template value. But its not.
For example, if I say xyz<20> a and then xyz<30> b(a), the compiler gives an error.
Why is this so?
Because they are different types. Even for this empty class template
template <int N> struct Foo {};
Foo<1> is a different type to Foo<2>. When such a template is instantiated with a template parameter, it creates a distinct class, irrespective of whether the template parameter is used in the code of the class. A class template is a recipe (a template) for building a class according to some (template) parameters.
Now, if you want to be able to construct one Foo instnatiation from another, then you can add an implicit converting constructor:
template <int N>
struct Foo
{
template <int M> Foo(const Foo<M>& rhs) {}
};
Then you can implicitly convert between one and the other:
Foo<42> a;
Foo<1> b (a);
Foo<99> c;
c = b;
Each time you use a different value of N, the compiler will create a new class definition.
Using template value or not change nothing.
it's the same for function parameters :
int foo(void) { // foo is of type `int (*)()`
return 1;
}
int bar(int not_used) { // bar is of type `int (*)(int)`
return 1;
}
bar don't use parameter, but it hasn't the same signature as foo.
Like you can't assign foo or bar to a same variable (because their types differs), you can't mix instances of xyz<0> and xyz<1>.
If you want to do this, you shoud consider using a classic inheritance.
Template type equivalence rules are explicitly written out in the Standart (paragraph 14.4). One rule states:
Two template-ids refer to the same class or function if
their corresponding non-type template arguments of integral or enumeration type have identical values
Thus, different numeric template arguments will yield different types, regardless whether they are actually used or not. In the latter case you might want to use template copy constructor:
template<int N>
class xyz{
template<int M>
xyz::xyz(const xyz<M>&);
};
How do you want compiler to prove that?
Consider:
template<int N>
class xyz{
void foo () {external_function (N);}
};
Do you suggest compiler to go and check what external_function does?
Besides having compiler produce compatible types on the grdounds of N not being used would have been a maintanence nightmare.
I assume you mean "copy-constructible and assignable from each other" when you say compatible.
You will need to define the copy-constructor and assignment operator
to handle classes instantiated with arbitrary values of int.
template<int N>
class Foo {
public:
template<int NO>
Foo(const Foo<NO>& other) {
// do stuff
}
template<int NO>
Foo& operator=(const Foo<NO>& other) {
// do stuff
return *this;
}
};
I would like to define a nullary static template member function which would be (explicitly) specialized on pointer-to-data-member and could have, for each specialization, different return type.
It should return some detailed information about each attribute, hence I will call this method trait. The trait object type returned will be inspected by other templates, so this whole machinery must be available at compile-time.
So far I have something like this (broken code, of course):
class Foo{
// some data members
int a; std::string b; int c;
// how to declare generic template here?
// compile-time error should ensue if none of the specializations below is matched
// specialization for a (aTraitExpr is expanded from macro, so it is OK to repeat it)
template auto trait<&Foo::a>()->decltype(aTraitExpr){ return aTraitExpr; }
// specialization for b; the return type will be different than for trait<&Foo::a>
template auto trait<&Foo::b>()->decltype(bTraitExpr){ return bTraitExpr; }
};
// some code which queries the trait at compile-time
// e.g. supposing all possible trait types declare isSerializable
// which happens to be True for a and False for b
Foo* foo;
template<bool isSerializable> void doSerialization(...);
template void doSerialization<true>(...){ ... };
template void doSerialization<false>(...){ /* no-op */ };
doSerialization<Foo::trait<&Foo::a>()::isSerializable>(...); // -> doSerialization<true>(foo)
doSerialization<Foo::trait<&Foo::b>()::isSerializable>(...); // -> doSerialization<False>(...)
doSerialization<Foo::trait<&Foo::c>()::isSerializable>(...); // -> compile error, specialization Foo::trait<&Foo::c> not defined
Could get some hint on how to achieve this? (I am not trying to invent a new serialization system, I already use boost::serialization; there will be more information in each trait, this is just for an example why it is needed at compile-time).
EDIT: I was able to get something nearing what I want, it is shown at ideone.com. I gave up having trait<Foo::a>() (for now), so there is static function getTrait_a() which returns reference to modifiable type-traits, which are however partially fixed at compile-time (so that Foo::TraitType_a::flags works, for instance). Thanks to everybody who replied, unfortunately I can only pick one of the answers as "answer".
It looks like you want several overloads instead of specializations. Unfortunately you don't detail on what xTraitExpr is, but it seems it's just a type that has a member isSerializable defined. I would probably go like this
class Foo {
// your members have been omitted to save space...
template<typename T, T Foo::*M>
struct W { };
static decltype(aTraitExpr) trait(W<int, &Foo::a>) {
return aTraitExpr;
}
static decltype(bTraitExpr) trait(W<std::string, &Foo::b>) {
return bTraitExpr;
}
// other overloads for other members...
public:
// overloads for each member type
template<int Foo::*M>
static decltype(trait(W<int, M>())) trait() {
return trait(W<int, M>());
}
template<std::string Foo::*M>
static decltype(trait(W<std::string, M>())) trait() {
return trait(W<std::string, M>());
}
};
trait(W<M>()) is a dependent call. A dependent call does ADL at definition and instantiation time and unqualified lookup only at definition time. That's why W and the additional trait overloads using it must be defined before the trait type overloads instead of after them, or the result of resolution in the return type and body of the functions will be different since they are parsed at different times (bodies are late parsed after the class definition, and return types are parsed immediately).
You can either make trait a constexpr function and make xTraitExpr be a literal class with a constexpr constructor initializing isSerializable appropriately, or you could apply decltype as follows
doSerialization<decltype(Foo::trait<&Foo::a>())::isSerializable>(...);
I think it doesn't make sense to use a function template here. That being said, using a class template in its stead isn't that convenient either: you have to account for the fact that the non-static data members can have different types and there can be several non-static data members with the same type. Here's a possibility:
template<typename T>
struct is_serializable: std::false_type {};
struct Foo {
int a; std::string b; int c;
// Primary template left undefined on purpose
// alternatively, could use a static_assert on a dependent
// std::false_type::value for better diagnostics
template<typename T, T t>
struct attribute_trait;
};
// Define explicit specializations outside of class
template<>
struct Foo::attribute_trait<int Foo::*, &Foo::a>
: is_serializable<int> {};
template<>
struct Foo::attribute_trait<std::string Foo::*, &Foo::b>
: is_serializable<std::string> {};
Which is usable as
doSerialization<Foo::attribute_trait<decltype(&Foo::a), &Foo::a>::value>(/* stuff */);
The usual way to define a traits class is by wrapping a struct/class around a compile-time constant expression (and not by wrapping a function returning such an expression). The syntax to take a class member function is like this:
template
<
SomeReturnType (SomeClass::*SomeMemberFunction)(SomeParameters)
>
class SomeTrait
{
static const value = SomeCompileTimeConstantExpression;
};
In your case, you would do it like that:
template
<
void (Foo::*f)()
>
class trait
{
static const value = fTraitExpr;
};
You then specialize this trait for all member functions of class Foo:
template<>
class trait<&Foo::a>
{
static const value = aTraitExpr;
};
// same for Foo::b and Foo::c
Furthermore, it is more idiomatic to overload function templates than to specialize them:
template<int V> struct Int2Type { enum { value = V }; };
Foo* foo;
template
<
void (Foo::*f)()
>
void doSerialization(...)
{
dispatch::doSerialization(Int2Type< trait<f>::value >(), ...);
}
namespace dispatch {
doSerialization(Int2Type< true >, ...) { ... };
doSerialization(Int2Type< false >, ...) { /* no-op */ };
} // namespace dispatch
You can then call it like this:
doSerialization<&Foo::a>(...);
doSerialization<&Foo::b>(...);
doSerialization<&Foo::c>(...);
In templates as shown below, I would like the call Run(&Base::foo) succeed without the need to name the Base type twice (as is done in the compiling Run<Base>(&Base::foo) call). Can I have that? Possibly without adding a ton of Boost headers?
With the provided code, I get an error of:
prog.cpp:26: error: no matching function for call to ‘Run(bool (Base::*)())’
(you can fiddle with the snippet at http://ideone.com/8NZkq):
#include <iostream>
class Base {
public:
bool foo() { return true; }
};
Base* x;
template<typename T>
struct Traits {
typedef bool (T::*BoolMethodPtr)();
};
template<typename T>
void Run(typename Traits<T>::BoolMethodPtr check) {
T* y = dynamic_cast<T*>(x);
std::cout << (y->*check)();
}
int main() {
Base y;
x = &y;
Run<Base>(&Base::foo);
Run(&Base::foo); // why error?
}
The T in Traits<T>::BoolMethodPtr is in a non-deduced context, so the compiler will not deduce automatically from the call what type T should be.
This is because there could be code like this:
template<typename T>
struct Traits {
typedef bool (T::*BoolMethodPtr)();
};
template<>
struct Traits<int> {
typedef bool (Base::*BoolMethodPtr)();
};
Run(&Base::foo); /* What should T be deduced to? Base and int are both equally possible */
If you can do without the Traits<T> class, you can write Run as:
template<class Class>
void Run(bool (Class::*check)()) {
Class* y = dynamic_cast<Class*>(x);
std::cout << (y->*check)();
}
In this context, Class can be deduced to mean Base
To pick apart a type, any type, use partial specialization. There is no function template partial specialization, so you'll need to directly parameterize the function on its argument type and retrieve the class type inside.
template< typename T >
struct get_host_class; // most types are not ptmfs: don't implement this
template< typename C >
struct get_host_class< bool (C::*)() > { // implement partial specialization
typedef C host;
typedef void sfinae; // disallow function for non ptmf arguments
};
template< typename T >
typename get_host_class<T>::sfinae Run( T check) {
typedef T BoolMethodPtr; // or something
typedef typename get_host_class< T >::host host;
}
I think this is a non deduced context.
$14.8.2.5/5- "The non-deduced contexts
are: — The nested-name-specifier of a
type that was specified using a
qualified-id."
I think this is the quote that applies in this case. But some template gods need to ratify my understanding.
When the compiler tries to match a template argument, it only considers the primary class type. In other words, when it encounters the expression:
Run(&Base::foo);
...and it's trying to figure out the template parameter for Run, it only considers the type of foo itself, and doesn't consider whatever class foo is a part of.
EDIT:
And the type of foo is bool(Base::*)(void), but what you want the compiler to find is just Base