I am writing a simple program to define systems that has vectors representing the states. I would like to have a declaration type of the vector of Eigen depending on the number of states in the derived class.
I tried to achieve this using templates on aliases, something like the code shown below
#include <iostream>
#include <Eigen/Core>
#include <Eigen/Dense>
using namespace std;
using namespace Eigen;
class A
{
public:
template <int T>
using StateVector = typename Matrix<double, T, 1>;
};
class B : public A
{
public:
int NUM_STATES = 5;
B(){
StateVector<NUM_STATES> a;
a.setIdentity();
cout<<a<<endl;
}
};
int main(){
B b;
}
I ultimately want to have a type that can be used in the derived classes. Is this possible?
With two minor changes, your code works fine.
First, there must be no typename keyword here:
template <int T>
using StateVector = Matrix<double, T, 1>;
Second, NUM_STATES must be a compile-time constant, i.e., either declare it as element of an enum or as static const int (or static constexpr int, if you prefer):
static const int NUM_STATES = 5;
Full working example on godbolt: https://godbolt.org/z/_T0gix
Related
I'm poking around in the myst of C++ instantiation / declaration order. Here's a fun bit I came across:
This compiles :
#include <cstddef>
#include <variant>
#include <array>
template <size_t V>
struct container
{
// THIS COMPILES
struct array;
using val = std::variant<std::monostate, int, array>;
// THIS DOESNT
// using val = std::variant<std::monostate, int, struct array>;
struct proxy : val
{
using val::variant;
};
struct array { };
};
int main()
{
container<10> ctr;
}
But when you opt for in-place declarations, it suddenly stops working (Demo):
#include <cstddef>
#include <variant>
#include <array>
template <size_t V>
struct container
{
// THIS COMPILES
// struct array;
// using val = std::variant<std::monostate, int, array>;
// THIS DOESNT
using val = std::variant<std::monostate, int, struct array>;
struct proxy : val
{
using val::variant;
};
struct array { };
};
int main()
{
container<10> ctr;
}
This is the error I get:
/opt/compiler-explorer/gcc-trunk-20220729/include/c++/13.0.0/type_traits:1012:52: error: static assertion failed: template argument must be a complete class or an unbounded array
1012 | static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
|
Can someone explain me exactly why this happens? What is the difference?
EDIT: You are allowed in certain circumstances to declare a type in a template argument list:
#include <cstddef>
#include <variant>
#include <array>
#include <cstdio>
void foo(std::initializer_list<struct array>);
struct array
{
array(int a) : a_{a} {}
void print() {
printf("%d\n", a_);
}
int a_;
};
void foo(std::initializer_list<struct array> init) {
for (auto a : init) {
a.print();
}
printf(".. it works\n");
}
int main()
{
foo({1,2,3});
}
I don't know when and where this applies though.
A declaration of the form
class-key attribute-specifier-seq(opt) identifier;
(where class-key means struct, class, or union), declares the identifier in the scope where the declaration appears ([dcl.type.elab]/2). That means in your first code snippet, array is forward declared as a member class of the container class template and you can later define it within the same scope.
When an elaborated-type-specifier such as struct array appears as a component of some larger declaration or expression, [dcl.type.elab]/3 applies. First, the compiler looks up the name array, ignoring anything that is not a type ([basic.lookup.elab]/1). If it doesn't find anything, then it forward-declares array in "the nearest enclosing namespace or block scope". Consequently, the struct array that you later define as a nested class is a different class, and the one you referred to as struct array earlier has no definition.
How make the following compile correctly with C++20, a.k.a calculate extract<mem_fun>::type? Is it possible?
Error-scenarios like passing non-member function or private function extract<> are not so important for me.
#include <concepts>
struct x
{
void f()
{
}
};
template<auto mem_fun>
struct extract
{
// using type= ???
};
int main()
{
using namespace std;
static_assert(same_as<typename extract<&x::f>::type, x>);
return 0;
}
Pointers to members all have type T C::*, where T can be either some type or some function type or even some "abominable" function type.
So you just need to specialize on that particular shape:
template<auto mem_fun>
struct extract;
template <typename T, typename C, T C::* v>
struct extract<v> {
using type = C;
};
The title might seem a little confusing, so here is a more thorough explanation:
I have a templated class that has a vector as a member variable. The template argument is a struct (or class) that will have one certain variable. The type of this vector shall be derived from the template argument (from this one certain variable). The tricky part is that it shall be derived from a member variable of the template argument.
#include <vector>
#include <complex>
using namespace std;
struct thingA {
double variable;
//...
};
struct thingB {
complex<double> variable;
//...
};
template <class S>
class someClass {
vector< " type of S::variable " > history; // If S=thingA, make it a double, if S=tingB make it a complex<double>
}
// Usage:
someClass<thingA> myInstanceA; // (this instance should now have a vector<double>)
someClass<thingB> myInstanceB; // (this instance should now have a vector<complex<double>>)
You can get the type via decltype, if the names of data member are always the same:
template <class S>
class someClass {
vector< decltype(S::variable) > history; // if S=thingA, make it a double, if S=tingB make it a complex<double>
};
I would define the type in the structs and use it in the class:
#include <vector>
#include <complex>
using namespace std;
struct thingA {
using Type = double;
Type variable;
//...
};
struct thingB {
using Type = complex<double>;
Type varbiable;
//...
};
template <class S>
class someClass {
vector<typename S::Type> history; // if S=thingA, make it a double, if S=tingB make it a complex<double>
};
// usage:
someClass<thingA> myInstanceA; // (this instance should now have a vector<double>)
someClass<thingB> myInstanceB; // (this instance should now have a vector<complex<double>>)
https://godbolt.org/z/raE9hbnqW
That is also the way to go when the variables do not have the same name.
I want to pass an std::array as an argument to a function, and I cannot find the correct way.
I am not talking about normal C array (e.g. int arr[2]={1,3};).
I am talking about std::array class, available from C++ 11.
Example code:
#include <iostream>
#include <array>
using namespace std;
class test
{
void function(array<int> myarr)
{
// .......some code..........
}
};
How do I pass an std::array to a function, as std::array takes two template arguments: std::array<class T, std::size_t N>, but while passing it as an argument I do not want to specify the size?
Not knowing the second template argument to std::array<> means your test class should be templated as well.
template <std::size_t N>
class test
{
void function(const std::array<int, N> & myarr)
{
// ...
}
};
By the way, it's better to pass myarr as const &.
You could use an approach like:
#include<array>
using namespace std;
template <size_t N>
class test
{
void function(const array<int, N> & myarr)
{
/* My code */
}
};
But keep in mind that std::array is not a dynamic array. You have to know the sizes at compile time.
If you get to know the sizes later at runtime of your program you should consider using std::vector instead:
#include<vector>
using namespace std;
class test
{
void function(const vector<int> & myvec)
{
/* My code */
}
};
In that variant you don't need to pass the size at all.
I don't know if this is possible at all, but I would like to "hide" some template parameters from a given class. Here's what I mean, say I have the following code:
template<class A, int b>
class Foo
{
};
template<template<class,int> class Foo_specialized, class A, int b>
class Bar
{
Foo_specialized<A,b> obj;
};
Now supposed Bar does not need to know about A, but needs to know about b.
Naturally something like this would be perfect (the following is a pseudo code just to illustrate the idea):
template<template<int> class Foo_specialized_by_first_parameter, int b>
class Bar
{
Foo_specialized_by_first_parameter<b> obj;
};
I'm not really sure if that's possible at all, the idea would be to have something like this when instancing Bar:
Bar<Foo<float>, 5> bar_instance;
Of course this does not work because Foo doesn't accept 1 parameter.
Basically I need something like (Foo<float>)<5> to be possible. The closest thing I can think of is currying in haskell.
You may use template typedef:
template <int N>
using Foo_float = Foo<float, N>;
And then, with
template <template<int> class Foo_specialized_by_first_parameter, int b>
class Bar
{
Foo_specialized_by_first_parameter<b> obj;
};
you may do:
Bar<Foo_float, 5> bar_instance;
Assuming for a second that you can change that int to std::integral_constant:
#include <iostream>
#include <string>
#include <map>
template<template<typename...> typename T, typename H>
struct Bind1st
{
template<typename... Arg>
using type = T<H, Arg...>;
};
int main() {
// to bind it
Bind1st< std::map, std::string >::type< std::string > mymap;
mymap[ "a" ] = "b";
}
Naturally, Bar< Bind1st< Foo, float >::type, 5 > should also work.