If it is possible, how could I avoid to write twice template < typename T> above my 2 functions making them still work for every argument type thew would have to work with?
And, even if it is possible, how could I write only the reverse_vector function making it contain "inside" the swap function, so I could be able to write template only once?
(I'm still a beginner learning basics and I absolutely don't know if there are better ways to do what I think you have understood I'd like. If yes, please say those. Thank you so much, good evening.)
#include <iostream>
#include <vector>
template <typename T>//HERE...
void swap(T& a, T& b) {
T tmp = a;
a = b;
b = tmp;
}
template <typename T>//...AND HERE
void reverse_vector(std::vector<T>& v) {
if (v.size() % 2 == 0) {
for (T i = 0; i < v.size() / 2; ++i) {
swap(v[i], v[v.size() - 1 - i]);
}
}
}
void print_vector(std::vector<short int>& v) {
for (unsigned short int i = 0; i < v.size(); ++i) {
std::cout << v[i] << '\n';
}
}
int main() {
unsigned short int g;
std::cout << "How large do you want the vector? _";
std::cin >> g;
std::vector <short int> v(g);
for (unsigned short int i = 0; i < g; ++i) {
v[i] = i + 1;
}
print_vector(v);
std::cout << "\n\n\n";
reverse_vector(v);
print_vector(v);
return 0;
}
You can not write template <typename T> only once. But you can write it not at all with c++20:
#include <concepts>
void swap(auto a, auto b) requires std::same_as<decltype(a), decltype(b)> {
auto tmp = a;
a = b;
b = tmp;
};
The requires clause is there to make sure you don't accidentally swap something of different types. I probably just broke the whole semantic and make swap copy everything. Think whether you need auto, auto&, auto&& to get the right semantic for swap before you use it.
PS: use std::ranges::swap
In trying to implement a suggested answer here in my own context, I am running into a compilation error.
Consider code:
#include <iostream>
class SIMPLE {
public:
SIMPLE() { for (int i = 0; i < 5; i++) val[i] = 5; };
int retval(int index) { return val[index]; }
private:
int val[5];
};
void print_array_of_length5(int (*fnptr)(int index)){
for (int i = 0; i < 5; i++)
printf("%d ", fnptr(i));
}
int global_array[5] = { 0, 1, 2, 3, 4 };
int global_function(int index){
return global_array[index];
}
int main(){
print_array_of_length5(&global_function);//Works fine.
int (SIMPLE::*p)(int) = &SIMPLE::retval;//Following method suggested in the answer above
class SIMPLE smpl;
print_array_of_length5(smpl.*p);//Compile error: a pointer to a bound function may only be used to call the function
}
The function works when supplied with the address of a global function. It does not work when passed smpl.*p analogous to the method suggested. How should one fix this error?
You need another overload for print_array_of_length5 in order to pass a member function pointer:
template<typename T>
void print_array_of_length5(int (T::*fnptr)(int index), T& obj)
{
for(int i = 0; i < 5; ++i)
{
printf("%d ", (obj.*fnptr)(i));
}
}
int main()
{
SIMPLE smpl;
print_array_of_length5(&SIMPLE::retval, smpl);
}
You can't pass a non-static member function pointer as a regular function pointer. Member functions have access to the this pointer, and the way they get that is via an invisible implicit function parameter. You need to have the object on which to call the function, and the function itself, be bound together, which a function pointer simply can't do.
What we can do is make print_array_of_length5 a function template, and allow it to take any type of callable. That would give you something like this:
template <typename Function>
void print_array_of_length5(Function func){
for (int i = 0; i < 5; i++)
printf("%d ", func(i));
}
To call it with a non-static member function, you can use a lambda expression, or std::bind(), like this:
SIMPLE smpl;
print_array_of_length5([&smpl](int foo){ return smpl.retval(foo); });
using namespace std::placeholders;
SIMPLE smpl;
auto func = std::bind(&SIMPLE::retval, &smpl, _1);
print_array_of_length5(func);
I want threading with template class parameter, but I don't know how I can use template class as parameter of thread method.
I already tried making method in template class, but I don't want it. People generally do not use this solution.
//....
//Linked List code
//.....
void func1(slist<T> s){
for (int i = 0; i < 1000; i++) {
s.push_(i);
}
} // this part is problem of my code.
int main() {
int i;
slist<int> s;
thread t1(func1,s); //Compile error.
func1(s); // here, too.
return 0;
}
i expect the result that threads compete with Linked list.
The generic solution:
template<typename T>
void func1(slist<T>& s){
for (int i = 0; i < 1000; i++) {
s.push_(i);
}
}
Or you can specialise for one specific type:
void func1(slist<int>& s){
for (int i = 0; i < 1000; i++) {
s.push_(i);
}
}
(Also be aware that you probably want to pass a reference to the list, rather than a copy)
As you want to make the thread accept a template, the function should be templated too.
template <typename T>
void func1(slist<T> s){ // most likely you need to pass by reference
for (int i = 0; i < 1000; i++) {
s.push_(i);
}
}
While calling the function in main,
int main() {
int i;
slist<int> s;
thread t1(func1<int>,s); //t1 needs to know which type it needs to instantiate of func1
t1.join(); // let the thread finish
return 0;
}
I have something like:
Array definition:
array<array<Value, N_FOO_PER_BAR>, N_BAR> arr;
Access function:
Value getFoo(int barIdx, int fooIdx){
return arr[barIdx][fooIdx];
}
For-loop:
for(int i = 0; i < N_BAR; i ++){
for(int j = 0; j < N_FOO_PER_BAR; j ++){
arr[i][j].doSomething();
}
}
Problem: Indices for foo and bar can easily get mixed up when using getFoo(...).
I would like to define a type BarIdx and FooIdx and then the compiler should complain when I mix them up.
The access function would then look like:
function getFoo(BadIdx barIdx, FooIdx fooIdx){
return arr[barIdx][fooIdx];
}
The for-loop could look like:
for(BarIdx i = 0; i < N_BAR; i ++){
for(FooIdx j = 0; j < N_FOO_PER_BAR; j ++){
arr[i][j].doSomething();
}
}
So I'm looking how to define a type which (a) will issue a warning/error when used at the wrong place but (b) still behaves as much as an integer as possible, for for loop and array access with []. This should also work on CUDA, so I would prefer to use simple language constructs rather than a perfect solution.
The difficulty with doing this is that you can't simply inherit from int in C++, so you need to provide a wrapper which not only implicitly converts to and from int, but also provides all the necessary operators so that you can do things like:
BarIdx a = 0;
++a;
You might want to start with something simple like this:
template <typename T>
class IntegralWrapper {
T value;
public:
typedef T value_type;
IntegralWrapper() :value() {}
IntegralWrapper(T v) :value(v) {}
operator T() const { return value; }
};
Then add any operators you need later. You would then define your index classes like this:
class BarIdx : public IntegralWrapper<int> {};
class FooIdx : public IntegralWrapper<int> {};
Alternatively, here is a seemingly pretty complete integral wrapper solution taken from this question which you could probably use.
It will not trivial. The problems is not in defining the type for index, but that the operator [] of the array take size_type (std::size_t) which will reduce to null all your effort to differenciate the indexes.
I will suggest another kind of sintactic sugar:
struct Idx {int bar, foo;};
Access function:
Value& getValue(Idx i){
return arr[i.bar][i.foo];
}
For-loop:
for(Idx i{0,0} ; i.bar < N_BAR; i.bar ++){
for(i.foo = 0; i.foo < N_FOO_PER_BAR; i.foo ++){
getValue(i).doSomething();
}
}
but also:
for(auto &foos : arr){
for(auto &foo : foos){
foo.doSomething();
}
}
I need to implement a generic algorithm that can operate on a matrix regardless of its representation. It could be a C-style 2D array, a vector of vectors or an arbitrary user class (which does not necessarily provide a subscript operator).
An obvious solution could look like this:
template<typename M>
void func(M& mat, int cols, int rows)
{
for(int j = 0; j < rows; ++j)
for(int i = 0; i < cols; ++i)
doSomething(elem(mat, i, j));
}
...where the user would have to provide an overload of 'elem' that operates on his matrix type. The problem with this approach is that this overload would need to be declared before 'func' for the code to compile, and not just before the template instantiation. Is there a way around this problem that does not involve an ugly function signature or forcing the user to write a wrapper class and other boilerplate code?
I have tried it and found a possible solution after my first comment. So Just including the declaration into the generic function, it works! See my example code below.
The point finally seems to be that the templetized code doesn't get the declaration of elem() done in the non-templetized code.
It's after the definition of the template, but before of its first instantiation, so, to my knowledge/understanding, it should be enough.... but my complier (gcc 4.8.2) complains as well. I'm sure to have used this feature many times with templetized methods and classes.
It seems really strange to me and possibly a bug (#Potatoswatter: can you give a reference to the bug - see if this match?).
EDITED: Finally understood. Still studying C++11 Stroustrup's! It works as intended in the standard. I give here some pointers - excerpts.
The first important idea is suggested in 23.3.2 (Templates, Error detection): Syntax error are checked in definitions before they are used in the first instance. Sure they are, but though that it was just defined later. But: "a name used in a template definition must either be in scope or in some reasonably obvious way depend on a template parameter". This is clear enough already now, but most important is the rationale behind this idea.
It's explained in great detail in 26.3 (Instantiation [of templates!], Name Binding): "Define template functions to minimize dependencies on nonlocal information. The reason is that a template will be used to generate functions and classes based on unknown types and in unknown contexts. Every subtle context dependency is likely to surface as a problem for somebody...".
After reading it - I'm still asking myself why I haven't thought to such an important difference, with respect to the controlled environment present within a generic class!!
Explanation go on (pages 745-758!) and the mechanism for the resolution is explained especially in 26.3.2 (Point-of-definition Binding) and 26.3.3 (Point-of-instantation Binding):
"When the compiler sees a template definition, it determines which names are dependent (26.3.1). If a name is dependent, looking for its declaration is postponed until instantiation time (26.3.3)."
"Names that do not depend on a template argument are treated like names that are not in templates; they must be in scope (6.3.4) at the point of definition".
That's stoned. elem() must be declared before it's used in the template definition - it is treated like names that are not in templates.
I agree with #Potatoswatter and others. This is probably the less elegant solution, since it restricts to the use of an external function, no functors, no lambdas.
On the other side, it addresses the problem (thought it was a workaround initially... no, it's just how it's intended to work!) of the OP.
#include <iostream>
using namespace std;
template<typename M, typename R>
void func(M mat, int cols, int rows)
{
// with this declaration it works.
R &elem(M, int, int);
for(int i = 0; i < cols; ++i) {
for(int j = 0; j < rows; ++j) {
elem(mat, i, j) += 1; // +=1 is just your "doSomething()"
}
}
}
template<typename M, typename R>
void show(M mat, int cols, int rows)
{
R &elem(M, int, int);
for(int i = 0; i < cols; ++i) {
for(int j = 0; j < rows; ++j) {
if (j>0) cout << ", ";
cout << elem(mat, i, j);
}
cout << endl;
}
}
float &elem(float *m, int i, int j) {
return m[i*3+j];
}
float &elem(float m[3][3], int i, int j) {
return m[i][j];
}
int main(int argc, char **argv) {
float mat1d[9] = {1,2,3,4,5,6,7,8,9};
float mat2d[3][3] = {1,2,3,4,5,6,7,8,9};
func<float*, float>(mat1d, 3, 3);
show<float*, float>(mat1d, 3, 3);
func<float(*)[3], float>(mat2d, 3, 3);
show<float(*)[3], float>(mat2d, 3, 3);
}
Trying to use references as in your question I've got slightly crazy before understanding that mixing them with statically declared sizes, let things much more stuck. I include it here because I have lost quite some time trying to get around this:
#include <iostream>
using namespace std;
template<typename M, typename R>
void func(M &mat, int cols, int rows)
{
R &elem(M&, int, int);
for(int i = 0; i < cols; ++i) {
for(int j = 0; j < rows; ++j) {
elem(mat, i, j) += 1; // +=1 is just your "something"
}
}
}
template<typename M, typename R>
void show(M &mat, int cols, int rows)
{
R &elem(M&, int, int);
for(int i = 0; i < cols; ++i) {
for(int j = 0; j < rows; ++j) {
if (j>0) cout << ", ";
cout << elem(mat, i, j);
}
cout << endl;
}
}
float &elem(float (&m)[9], int i, int j) {
return m[i*3+j];
}
float &elem(float (&m)[3][3], int i, int j) {
return m[i][j];
}
int main(int argc, char **argv) {
float mat1d[9] = {1,2,3,4,5,6,7,8,9};
float mat2d[3][3] = {1,2,3,4,5,6,7,8,9};
func<float[9], float>(mat1d, 3, 3);
show<float[9], float>(mat1d, 3, 3);
func<float[3][3], float>(mat2d, 3, 3);
show<float[3][3], float>(mat2d, 3, 3);
}
NOTE: in this way elem() is a function, included at link time. I think that's not what you want, but then you can get around it making a functor of all the stuff.
The easiest solution is that a subscript operator should be mandatory.
You are ok to force the user to declare a elem function, but you don't want to force him to overload a subscript operator. This doesn't make sense to me. Consider the case when he uses an array or a class that already has a subscript operator defined. Why would you force him to define a function that does what the subscript operator already does?
However this is how you do what you want:
template<typename M, typename F>
void func(M& mat, int cols, int rows, F elem)
{
for(int j = 0; j < rows; ++j)
for(int i = 0; i < cols; ++i)
doSomething(elem(mat, i, j));
}
This can be called with references to functions, pointer to functions or lambdas.
Call example with lambda:
func(mat, 5, 5, []->int (int **m, int i, int j) { return m[i][j];});
I haven't test it so I hope there are no syntax errors.
As a middle ground beside that you could have an overload what doesn't receive elem as a parameter and uses the subscript operator.
The problem with this approach is that this overload would need to be declared before 'func' for the code to compile, and not just before the template instantiation.
This sounds like a misunderstanding; it's much stronger than the actual requirement. The overload called by a particular specialization only needs to be declared before the point of instantiation of that specialization, i.e. before whatever non-template call in each translation unit that first leads to your template.
Before the template definition, you only need some function named func; it doesn't need to remotely match the call or to be useable for any purpose. It's just a placeholder to let the parser know that your template is making a function call there. This would do fine:
void elem( struct unused_tag_type ) = delete;
as would this:
void elem();
Below is my attempt towards a minimal running sample to demonstrate the problem, and a solution. I have only been able to produce the problem when functions and data are defined in different namespaces. I think this is the most general case.
Problem (live example):
namespace X { struct A {}; }
namespace Y { // function-style
template<typename T>
void f(T x) { h(x); }
void g() { f(X::A{}); }
void h(X::A) { cout << "Hello, world!" << endl; }
}
Solution (live example):
namespace X { struct A {}; }
namespace Y { // functor-style
template<typename T>
struct H;
template <typename T>
void h(T x) { H<T>()(x); }
template<typename T>
void f(T x) { h(x); }
void g() { f(X::A{}); }
template<>
struct H<X::A>
{
void operator()(X::A) { cout << "Hello, world!" << endl; }
};
}
In words, use a template struct (function object, H) to do the job and a template function (h) only as a wrapper. H can be specialized whenever you like (but in the same namespace). Its general declaration and the declaration of h should appear before the point of instantiation in g().
Limitation (live example): Unfortunately, this does not work if the return type is unknown, that is, if you replace H and h by the most general forms
template<typename... T>
struct H;
template <typename... T>
auto h(T&&... x)
->decltype(H<T...>()(std::forward <T>(x)...))
{ return H<T...>()(std::forward <T>(x)...); }
I've tried and it doens't even work with -std=c++1y without the training return type. But I hope this is not an issue in your case.