I have a matrix class and a column class inside it:
template<class T>
struct MatrixT
{
template<class T>
struct ColumnT
{
};
};
Note that a ColumnT will always hold the same type as a MatrixT.
For convenience I define
typedef MatrixT<double> matrix;
Since in reality, I'll be using a double element most of the time. But I also want to define something similar for the columnT class. I tried
typedef MatrixT<double>::ColumnT<double> matrix::column;
but compilation fails with the error
Error - qualified name is not allowed
Is there a way of achieving what I want?
I'd like to be able to type matrix::column c; just as I can type matrix m;
Just remove the second template<class T>
template<class T>
struct MatrixT
{
struct ColumnT
{
};
};
ColumnT should then be using the same type as MatrixT, and your typedef...
typedef MatrixT<double> matrix;
...should work as you are expecting it to.
Related
I want to use a pointer to a class member as a template parameter as in:
template <class Class, class Result, Result Class::*Member>
struct MyStruct {
// ...
};
Using this struct like MyStruct<SomeClass, SomeResult, &SomeClass::value> variable works just fine, but I don't like that I have to specify SomeClass and SomeResult.
I would like to use MyStruct<&SomeClass::value> variable if that is possible, but without losing the ability to pass any class and have any result type.
I tried the following, but the syntax is illegal:
template <class Class, class Result>
template <Result Class::*Member>
struct MyStruct {
// ...
};
error: too many template-parameter-lists
I tried using a helper function (that does actually work in Clang but is refused by GCC):
template <class Class, class Result>
static constexpr auto makeMyStruct(Result Class::*member) ->
MyStruct<Class, Result, member> {
// ...
}
error: use of parameter `member' outside function body
error: template argument 3 is invalid
Is it possible to have a simple MyStruct<&SomeClass::value>, and if so, how?
Related question that did not solve my question:
Pointer to class member as template parameter
C++0x error with constexpr and returning template function
In c++17, with the addition of auto in template arguments (P0127), I think you can now do:
template<auto value>
struct MyStruct {};
template<typename Class, typename Result, Result Class::* value>
struct MyStruct<value> {
// add members using Class, Result, and value here
using containing_type = Class;
};
typename MyStruct<&Something::theotherthing>::containing_type x = Something();
An answer to my question was proposed in this paper for the next upcoming C++ standard:
https://isocpp.org/files/papers/n3601.html
This syntax was proposed:
template<using typename T, T t>
struct some_struct { /* ... */ };
some_struct<&A::f> x;
The need for a new syntactical construct indicates that you cannot do that by now.
I hope n3601 will be accepted. :-)
This could be a solution in C++11:
You can define the following generic type traits:
template<class T>
struct remove_member_pointer {
typedef T type;
};
template<class Parent, class T>
struct remove_member_pointer<T Parent::*> {
typedef T type;
};
template<class T>
struct baseof_member_pointer {
typedef T type;
};
template<class Parent, class T>
struct baseof_member_pointer<T Parent::*> {
typedef Parent type;
};
Now you can define an additional, 4-line wrapper macro for every struct:
template<class Class, class Result, Result Class::*Member>
struct _MyStruct {
// ...
};
#define MyStruct(MemberPtr) \
_MyStruct<baseof_member_pointer<decltype(MemberPtr)>::type, \
remove_member_pointer<decltype(MemberPtr)>::type, \
MemberPtr>
... and use it in the following way:
MyStruct(&SomeClass::value) myStruct; // <-- object of type MyStruct<&SomeClass:value>
I use this as an intermediate solution, until we switch to C++17.
Make your result class a child of your template class. assuming the pointer member is an object of your result class in public or whatever, you can access any objects by doing something like this
template <stuff for this class> :: public result
{
blah
}
Is there any way to get a recursive template type? I have a container for which I want to specify an underlying storage strategy. The inner template must however use the outer template's type, so it causes a loop in the type definition -- which isn't possible to specify.
About what I want:
template<typename C>
struct inner {
C * object[16];
};
template<typename T, typename Inner>
struct container {
T value;
Inner<container> holder;
};
C++11 solutions are fine (though I'm still on gcc 4.6.3).
You need to tell the compiler that Inner is a templated class:
template<typename T, template<typename> class Inner>
struct container {
T value;
Inner<container> holder;
};
I'm not sure why you're adding the Inner type template parameter, since you're defining holder to be a type based on Container and inner, both of which are available at the point you're declaring holder.
Are you planning on using any type other than struct inner as a template param to Container? If not, the following simplified code compiled and ran for me in VS2010 :
#include <vector>
#include <stdio.h>
template <typename C>
struct inner{
C * objects[16];
bool hasobj;
inner():hasobj(false){}
};
template <typename T>
class Container {
inner<Container> holder;
T value;
public:
Container(const T& valueP){
value = valueP;
}
void AddChild(Container* rhs){
holder.objects[0] = rhs; //Always using first location, just for example
holder.hasobj = true;
}
void PrintStuff()const{
if(holder.hasobj){
holder.objects[0]->PrintStuff();
}
printf("VAL IS %d\n", value);
}
};
int main(){
Container<int> c(10);
Container<int> c1(20);
c1.AddChild(&c);
c1.PrintStuff();
}
Basically, this is assuming that the container is always defining holder in terms of inner, which helps get rid of the extra template parameter, when defining Container. Hope this helps :)
arun
I want to use a pointer to a class member as a template parameter as in:
template <class Class, class Result, Result Class::*Member>
struct MyStruct {
// ...
};
Using this struct like MyStruct<SomeClass, SomeResult, &SomeClass::value> variable works just fine, but I don't like that I have to specify SomeClass and SomeResult.
I would like to use MyStruct<&SomeClass::value> variable if that is possible, but without losing the ability to pass any class and have any result type.
I tried the following, but the syntax is illegal:
template <class Class, class Result>
template <Result Class::*Member>
struct MyStruct {
// ...
};
error: too many template-parameter-lists
I tried using a helper function (that does actually work in Clang but is refused by GCC):
template <class Class, class Result>
static constexpr auto makeMyStruct(Result Class::*member) ->
MyStruct<Class, Result, member> {
// ...
}
error: use of parameter `member' outside function body
error: template argument 3 is invalid
Is it possible to have a simple MyStruct<&SomeClass::value>, and if so, how?
Related question that did not solve my question:
Pointer to class member as template parameter
C++0x error with constexpr and returning template function
In c++17, with the addition of auto in template arguments (P0127), I think you can now do:
template<auto value>
struct MyStruct {};
template<typename Class, typename Result, Result Class::* value>
struct MyStruct<value> {
// add members using Class, Result, and value here
using containing_type = Class;
};
typename MyStruct<&Something::theotherthing>::containing_type x = Something();
An answer to my question was proposed in this paper for the next upcoming C++ standard:
https://isocpp.org/files/papers/n3601.html
This syntax was proposed:
template<using typename T, T t>
struct some_struct { /* ... */ };
some_struct<&A::f> x;
The need for a new syntactical construct indicates that you cannot do that by now.
I hope n3601 will be accepted. :-)
This could be a solution in C++11:
You can define the following generic type traits:
template<class T>
struct remove_member_pointer {
typedef T type;
};
template<class Parent, class T>
struct remove_member_pointer<T Parent::*> {
typedef T type;
};
template<class T>
struct baseof_member_pointer {
typedef T type;
};
template<class Parent, class T>
struct baseof_member_pointer<T Parent::*> {
typedef Parent type;
};
Now you can define an additional, 4-line wrapper macro for every struct:
template<class Class, class Result, Result Class::*Member>
struct _MyStruct {
// ...
};
#define MyStruct(MemberPtr) \
_MyStruct<baseof_member_pointer<decltype(MemberPtr)>::type, \
remove_member_pointer<decltype(MemberPtr)>::type, \
MemberPtr>
... and use it in the following way:
MyStruct(&SomeClass::value) myStruct; // <-- object of type MyStruct<&SomeClass:value>
I use this as an intermediate solution, until we switch to C++17.
Make your result class a child of your template class. assuming the pointer member is an object of your result class in public or whatever, you can access any objects by doing something like this
template <stuff for this class> :: public result
{
blah
}
Problem
Consider the following class
template <typename T>
struct A
{
T x;
};
Now, another class is templated like so:
template <typename T, typename U>
class B
{
protected:
std::vector<U> arr;
public:
T get_x(unsigned int p) { return arr[p].x; }
};
I would like to access the field A<T>::x from within B<T, A<T>>::get_x() and return it unaltered (i.e., keep its type as T). My poor knowledge of templating says that this requires knowing the type andof T it should be one of the template parameters of class B. However, that makes it possible to declare something inconsistent, like B<int, A<double>>, and in general sounds like an unnecessary repetition.
Questions
Is what I wrote an example of bad programming practice? How should this be written?
Is there a possibility of inferring the type T of A<T>::x and avoid two template types? It feels like a repetition, so I am not sure if there is a God-fearing, standard-abiding solution out there or not.
For what it is worth, I am using GCC 4.6.2 with -std=c++0x.
I would suggest an approach adopted by the Standard Library. Define a nested type.
template <typename T>
struct A
{
typedef T value_type; //this is nested type to be used by B
T x;
};
//this is another class added by me, just to demonstrate the genericity
template <typename T>
struct C
{
typedef T value_type; //this is nested type to be used by B
T x;
};
template <typename T>
class B
{
typedef typename T::value_type value_type; //get the nested type
protected:
std::vector<T> arr;
public:
value_type get_x(unsigned int p) { return arr[p].x; }
//^^^^^^^^^ note this
};
Usage:
B<A<int>> ba; //'>>' if C++11, otherwise use '> >' (separate them by space)
B<C<double>> bc; //works for C class template as well
I'm trying to do something like this (completely synthetic example, because the real code is a bit to convoluted):
enum MyInfoType
{
Value1, Value2
};
template<typename T> struct My_Type_Traits
{};
template<> struct My_Type_Traits<int>
{
typedef MyInfoType InfoType;
};
template<typename T>
class Wrap
{
template<My_Type_Traits<T>::InfoType INFO> int GetInfo()
{...}
};
...
Wrap<int> w;
int info = w.GetInfo<Value1>();
So basically I'm trying to use a typedef from inside another struct as type of a template parameter. With this code however the compiler complains that struct My_Type_Traits<T>::InfoType is not a type. So what do I need to do to make this work?
You need to use the typename keyword: like typename My_Type_Traits<T>::InfoType to let the compiler know you're referring to a nested type.