Adding class - syntax error identifer 'string' - c++-cli
Im trying to add new class to existing project. My class work corectly when it was under System::Windows::Forms::Form class inside Windows Form Application Project. I want to add my class to that project because i want all classes in different files. But when i want to compile I got error "syntax error : identifier 'String'". When i delete String object everything can be compiled. Where's problem ?
#ifndef ConGen
#define ConGen
template <class T>
ref class GenerateControls
{
public:
GenerateControls(int i , int j, int k,int l, int m)//, String ^ n)//, int o, int p)
: size(i),x(j),y(k),rozstawx(l),rozstawy(m), name(n), sizex(o), sizey(p)
{
tablica = gcnew array < T ^ >(size);
for ( int j = 0 ; j < i ; ++j)
{
tablica[j] = gcnew T();
tablica[j]->Name = String::Concat(n,Convert::ToString(j));
tablica[j]->Location = System::Drawing::Point(x+rozstawx*j,y+rozstawy*j);
//tablica[j]->Size = System::Drawing::Size(sizex,sizey);
tablica[j]->AutoSize = true;
tablica[j]->Visible = true;
}
}
~GenerateControls()
{
//for ( int j = 0 ; j < size ; ++ j )
//{
//}
}
property int Size
{
void set(int value)
{
//if(value < 0 ) throw
size=value;
}
int get()
{
return size;
}
}
property array< T ^ > ^ Tablica
{
array<T ^ > ^ get()
{
return tablica;
}
}
void SetVisible ( int i)
{
for( int j = 0 ; j < size ; ++j)
{
if ( j < i ) tablica[j]->Visible = true;
else tablica[j]->Visible = false;
}
}
void SetPosition( int x, int y, int odleglosc_x, int odleglosc_y, int ile)
{
for ( int i = 0 ; i<ile ; ++i)
{
Tablica[i]->Location = System::Drawing::Point(x+odleglosc_x*i,y+odleglosc_y*i);
}
}
private:
array < T ^ > ^ tablica;
int size;
int x;
int y;
int rozstawx;
int rozstawy;
int sizex;
int sizey;
// String ^ name;
};
#endif
I want to participate my code to few classes but something weird is happened. This is my Form class:
#pragma once
#include "ConGen.h"
namespace Trening {
using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Data::SqlClient;
using namespace System::Drawing;
public ref class okno2 : public System::Windows::Forms::Form
{
public:
okno2(void)
{
InitializeComponent();
}
protected:
~okno2()
{
if (components)
{
delete components;
}
}
private:
System::ComponentModel::Container ^components;
System::Windows::Forms::TabControl ^ tabcontrol;
System::Windows::Forms::TabPage ^ tabpage1;
System::Windows::Forms::TabPage ^ tabpage2;
System::Windows::Forms::TabPage ^ tabpage3;
System::Data::SqlClient::SqlConnection ^ sqlcon;
GenerateControls < System::Windows::Forms::TextBox > ^ tb1;
GenerateControls < System::Windows::Forms::TextBox > ^ tb2;
GenerateControls < System::Windows::Forms::TextBox > ^ tb3;
GenerateLabels < System::Windows::Forms::Label > ^ lb1;
GenerateLabels < System::Windows::Forms::Label > ^ lb2;
GenerateLabels < System::Windows::Forms::Label > ^ lb3;
array < String ^ > ^ stringtabs1;
array < String ^ > ^ stringtabs2;
array < String ^ > ^ stringtabs3;
array < String ^ > ^ textboxtabs1;
array < String ^ > ^ textboxtabs2;
array < String ^ > ^ textboxtabs3;
int clientwidth;
int clientheight;
#pragma region Windows Form Designer generated code
void InitializeComponent(void)
{
clientwidth = 300;
clientheight = 300;
this->tabcontrol = gcnew System::Windows::Forms::TabControl();
this->tabpage1 = gcnew System::Windows::Forms::TabPage();
this->tabpage2 = gcnew System::Windows::Forms::TabPage();
this->tabpage3 = gcnew System::Windows::Forms::TabPage();
this->tabcontrol->SuspendLayout();
this->tabpage1->SuspendLayout();
this->tabpage2->SuspendLayout();
this->tabpage3->SuspendLayout();
// tabcontrol
this->tabcontrol->Alignment = System::Windows::Forms::TabAlignment::Top;
this->tabcontrol->Controls->Add(this->tabpage1);
this->tabcontrol->Controls->Add(this->tabpage2);
this->tabcontrol->Controls->Add(this->tabpage3);
this->tabcontrol->Dock = System::Windows::Forms::DockStyle::Fill;
this->tabcontrol->HotTrack = true;
this->tabcontrol->Location = System::Drawing::Point(0,0);
this->tabcontrol->Multiline = true;
this->tabcontrol->Name = L"tabcontrol";
this->tabcontrol->SelectedIndex = 0;
this->tabcontrol->ShowToolTips = true;
this->tabcontrol->Size = System::Drawing::Size(215,129);
this->tabcontrol->TabIndex =1;
// tb1 & lb1
tb1 = gcnew GenerateControls< System::Windows::Forms::TextBox >(10,85,80,0,30,"tb1",145,35);
//lb1 = gcnew GenerateLabels< System::Windows::Forms::Label >(10,20,80,0,30,"lb1",35,20); <----------------------------- TU
// tabPage1
this->tabpage1->BackColor = System::Drawing::Color::PaleGreen;
this->tabpage1->Controls->AddRange(tb1->Tablica);
//this->tabpage1->Controls->AddRange(lb1->Tablica);
this->tabpage1->Location = System::Drawing::Point(4, 4);
this->tabpage1->Name = L"tabpage1";
this->tabpage1->Padding = System::Windows::Forms::Padding(3);
this->tabpage1->Size = System::Drawing::Size(207, 103);
this->tabpage1->TabIndex = 0;
this->tabpage1->Text = L"Dane";
this->tabpage1->ToolTipText = L"Informacje o użytkowniku";
this->tabpage1->UseVisualStyleBackColor = false;
//tb2 & lb2
tb2 = gcnew GenerateControls< System::Windows::Forms::TextBox >(10,85,80,0,30,"tb1",145,35);
//lb2 = gcnew GenerateLabels< System::Windows::Forms::Label >(10,20,80,0,30,"lb1",35,20); <----------------------------- TU
// tabPage2
this->tabpage2->BackColor = System::Drawing::Color::Plum;
this->tabpage2->Controls->AddRange(tb2->Tablica);
//this->tabpage1->Controls->AddRange(lb2->Tablica);
this->tabpage2->Location = System::Drawing::Point(4, 4);
this->tabpage2->Name = L"tabpage2";
this->tabpage2->Padding = System::Windows::Forms::Padding(3);
this->tabpage2->Size = System::Drawing::Size(207, 103);
this->tabpage2->TabIndex = 1;
this->tabpage2->Text = L"Wymiary";
this->tabpage2->ToolTipText = L"Wymiary poszczególnych partii";
this->tabpage2->UseVisualStyleBackColor = false;
//tb3 & lb3
tb3 = gcnew GenerateControls< System::Windows::Forms::TextBox >(10,85,80,0,30,"tb1",145,35);
//lb3 = gcnew GenerateLabels< System::Windows::Forms::Label >(10,20,80,0,30,"lb1",35,20); <----------------------------- TU
// tabPage3
this->tabpage3->BackColor = System::Drawing::Color::Plum;
this->tabpage3->Controls->AddRange(tb3->Tablica);
//this->tabpage1->Controls->AddRange(lb3->Tablica);
this->tabpage3->Location = System::Drawing::Point(4, 4);
this->tabpage3->Name = L"tabpage3";
this->tabpage3->Padding = System::Windows::Forms::Padding(3);
this->tabpage3->Size = System::Drawing::Size(207, 103);
this->tabpage3->TabIndex = 2;
this->tabpage3->Text = L"Osiągi";
this->tabpage3->ToolTipText = L"Twoje osiągi";
this->tabpage3->UseVisualStyleBackColor = false;
this->Controls->Add(this->tabcontrol);
this->tabcontrol->ResumeLayout(false);
this->tabpage1->ResumeLayout(false);
this->tabpage1->PerformLayout();
this->tabpage2->ResumeLayout(false);
this->tabpage2->PerformLayout();
this->tabpage3->ResumeLayout(false);
this->tabpage3->PerformLayout();
this->ResumeLayout(false);
this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
this->ClientSize = System::Drawing::Size(clientwidth, clientheight);
this->Name = L"Form1";
this->Text = L"Form1";
this->ResumeLayout(false);
}
#pragma endregion
}
};
}
And this is class GenerateControls & GenerateLabels (there are in one file because when they are split i can't compile).
#ifndef ConGen
#define ConGen
using namespace System;
namespace Trening
{
template <class T>
ref class GenerateControls
{
public:
GenerateControls(int i , int j, int k,int l, int m, String ^ n, int o, int p)
: size(i),x(j),y(k),rozstawx(l),rozstawy(m), name(n)//, sizex(o), sizey(p)
{
tablica = gcnew array < T ^ >(size);
for ( int j = 0 ; j < i ; ++j)
{
tablica[j] = gcnew T();
tablica[j]->Name = String::Concat(n,Convert::ToString(j));
tablica[j]->Location = System::Drawing::Point(x+rozstawx*j,y+rozstawy*j);
//tablica[j]->Size = System::Drawing::Size(sizex,sizey);
tablica[j]->AutoSize = true;
tablica[j]->Visible = true;
}
}
~GenerateControls()
{
//for ( int j = 0 ; j < size ; ++ j )
//{
//}
}
property int Size
{
void set(int value)
{
//if(value < 0 ) throw
size=value;
}
int get()
{
return size;
}
}
property array< T ^ > ^ Tablica
{
array<T ^ > ^ get()
{
return tablica;
}
}
void SetVisible ( int i)
{
for( int j = 0 ; j < size ; ++j)
{
if ( j < i ) tablica[j]->Visible = true;
else tablica[j]->Visible = false;
}
}
void SetPosition( int x, int y, int odleglosc_x, int odleglosc_y, int ile)
{
for ( int i = 0 ; i<ile ; ++i)
{
Tablica[i]->Location = System::Drawing::Point(x+odleglosc_x*i,y+odleglosc_y*i);
}
}
void SetSize( int x, int y, int ile)
{
// if (ile > Size ) throw
for ( int i = 0 ; i < ile ; ++i)
{
Tablica[i]->Size = System::Drawing::Size(x, y);
}
}
private:
array < T ^ > ^ tablica;
int size;
int x;
int y;
int rozstawx;
int rozstawy;
int sizex;
int sizey;
String ^ name;
};
#include "ConGen.h" // skopiowałem poprzez crtl + a całą klasę i zapomniałem usunąć tej linijki.
using namespace System;
template < class T >
ref class GenerateLabels : public GenerateControls< T > //: public SetControlText< T >
{
public:
GenerateLabels(int i , int j, int k,int l, int m, String ^ n, int o, int p)
:GenerateControls( i,j,k,l,m,n,o,p)
{
}
~GenerateLabels()
{
}
void SetText( array< String ^ > ^ name)
{
int i = 0;
//if (name.Size != controlarray.Size ) throw
for each ( String ^ str in name)
{
Tablica[i++]->Text = str;
}
}
};
}
#endif
With out code witch is marked "<--------Tu" i got error like these ( he is in first class okno2).
1>Trening.obj : error LNK2022: metadata operation failed (80131188) : Inconsistent field declarations in duplicated types (types: Trening.GenerateControls<System::Windows::Forms::Label>; fields: tablica): (0x04000033).
1>Trening.obj : error LNK2022: metadata operation failed (80131188) : Inconsistent field declarations in duplicated types (types: Trening.GenerateControls<System::Windows::Forms::Label>; fields: size): (0x04000034).
1>Trening.obj : error LNK2022: metadata operation failed (80131188) : Inconsistent field declarations in duplicated types (types: Trening.GenerateControls<System::Windows::Forms::Label>; fields: x): (0x04000035).
1>Trening.obj : error LNK2022: metadata operation failed (80131188) : Inconsistent field declarations in duplicated types (types: Trening.GenerateControls<System::Windows::Forms::Label>; fields: y): (0x04000036).
1>Trening.obj : error LNK2022: metadata operation failed (80131188) : Inconsistent field declarations in duplicated types (types: Trening.GenerateControls<System::Windows::Forms::Label>; fields: rozstawx): (0x04000037).
1>Trening.obj : error LNK2022: metadata operation failed (80131188) : Inconsistent field declarations in duplicated types (types: Trening.GenerateControls<System::Windows::Forms::Label>; fields: rozstawy): (0x04000038).
1>Trening.obj : error LNK2022: metadata operation failed (80131188) : Inconsistent field declarations in duplicated types (types: Trening.GenerateControls<System::Windows::Forms::Label>; fields: sizex): (0x04000039).
1>Trening.obj : error LNK2022: metadata operation failed (80131188) : Inconsistent field declarations in duplicated types (types: Trening.GenerateControls<System::Windows::Forms::Label>; fields: sizey): (0x0400003a).
1>Trening.obj : error LNK2022: metadata operation failed (80131188) : Inconsistent field declarations in duplicated types (types: Trening.GenerateControls<System::Windows::Forms::Label>; fields: name): (0x0400003b).
1>Trening.obj : error LNK2022: metadata operation failed (801311D7) : Differing number of fields in duplicated types (Trening.GenerateControls<System::Windows::Forms::Label>): (0x02000005).
1>Trening.obj : error LNK2022: metadata operation failed (8013118B) : Inconsistent implemented interfaces in duplicated types (types: Trening.GenerateControls<System::Windows::Forms::Label>; interfaces: System.IDisposable): (0x09000002).
1>LINK : fatal error LNK1255: link failed because of metadata errors
I think something is wrong with GenerateLabels class. Because when instance of that class isn't inicializet i got that errors. With GenerateControls everything works fine.
I don't see a using namespace System; in your code. Did you trim that when copy/pasting to the web, or do you need to add it?
I see you're referencing System::Drawing::Point and System::Drawing::Size by their full namespaces, could be you just need the using directive for System::String.
Related
Arduino - passing values by reference from lamda to singleton
Hello i am bigginer in programing and i have specific problem. I have been learning a new ways to write a code in small Arduino project. that project have multiple objects like distance measuring Senzor, led diods , temperature senzor, etc. And all this objects have its own menu where you can, for example, start a calibration or just get values. What i need is singleton class that has a function enter_esc() that need a int (*funct)() parameter basically function pointer. That enter_esc(int (*funct)()) function just looping function until you press escape pin which is defined. function Calibration() have inside some private: object data types like value or cali_value. so i tried to insert function Calibration() right into enter_esc(Calibration) but it won't compile becouse i didnt pass that vlaues by reference or copy. but what i found is lambda. i made a lamda similar to a Calibration() function and i passed values by reference &{//domething;} but i had to use enter_esc(std::function<int()>& funct) whitch is only int C++ standard library and not in Arduino C/C++ so my qestion is: [is there some way how to pass values by reference by using lambda to a singleton class in Arduino ?] (i konw it can be done differently but like i said i want to learn some new ways to program, also if you have some different way to make it i will by very happy to see it) 10Q for your time :) //Class.h #pragma once class events { private: static events e_instance; int p_menu, p_enter, p_esc, p_up, p_down; int menuValue; events(); public: events(const events&) = delete; static events& Get(); int ArrowUpDown(int maxVal); int ArrowUpDown(int p_up, int p_down, int maxVal); int enter_esc(const std::function<int()>& funct); }; events events::e_instance; class deviceBase : public Printables { public: const char* a_pin; int d_pin; String type; String deviceName; bool inUse; int actualCount; public: String getType() override; int getActualCount() override; String getName() override; String getInUse() override; }; class senzor : public deviceBase { private: int Value; int triggValue; public: int p_triggValue = 10; static int allSenzors; friend events; senzor(); ~senzor(); public: int getValue(); int Calibration(); void changeTriggVal(int x); void Reset(); void nullCalibration(); void Menu(int x); void setName(String deviceName); void setInUse(bool x); int getPin(); }; int senzor::allSenzors = 0; if you have some good advice to my code writing i will be also very glad //Class.cpp #include <iostream> #include <string> #include <functional> #define LOG(x) std::cout << x << std::endl; #define PINMENU 12 #define PINENTER 8 #define PINESC 9 #define PINUP 11 #define PINDOWN 13 using String = std::string; struct Printables { virtual String getType() = 0; virtual int getActualCount() = 0; ; virtual String getName() = 0; virtual String getInUse() = 0; }; #include "Class.h" events& events::Get() { return e_instance; } int events::ArrowUpDown(int maxVal) { if (maxVal) { menuValue = menuValue < maxVal ? menuValue++ : menuValue; } if (maxVal) { menuValue = menuValue > 0 ? menuValue-- : menuValue; } return menuValue; } int events::enter_esc(const std::function<int()>&funct) { if (1) { while (!p_esc) { auto f = funct; } } return 1; } int events::ArrowUpDown(int p_up, int p_down, int maxVal) { return 666; } events::events() {}; String deviceBase::getType() { return type; } int deviceBase::getActualCount() { return actualCount; } String deviceBase::getName() { return deviceName; } String deviceBase::getInUse() { String Status; Status = inUse == 1 ? "Active" : "Deactive"; return Status; } senzor::senzor() : Value(0), triggValue(1) { a_pin = "xx"; type = "[SENZOR]"; deviceName = "[UNKNOWN]"; inUse = 0; allSenzors++; actualCount = allSenzors; a_pin = 0; } senzor::~senzor() { allSenzors = 0; } int senzor::getValue() { Value = 4; return Value; } int senzor::Calibration() { triggValue = triggValue < getValue() ? getValue() : triggValue; p_triggValue = triggValue; return p_triggValue; } void senzor::changeTriggVal(int x) { p_triggValue = x; } void senzor::Reset() { p_triggValue = triggValue; } void senzor::nullCalibration() { triggValue = 1; } void senzor::setName(String deviceName) { this->deviceName = deviceName; } void senzor::setInUse(bool x) { inUse = x; } int senzor::getPin() { return 4; } int printsss() { return 1; } ////////////////////////////////this what i was writing about////////////////////////////// void senzor::Menu(int x) { events::Get().enter_esc([&]() { triggValue = triggValue < getValue() ? getValue() : triggValue; p_triggValue = triggValue; return p_triggValue; }); } but if i use lambda in arduino with enter_esc(int (*funct)()) i get this kind of error no matching function for call to 'events::enter_esc(senzor::Menu(int)::<lambda()>)'
How is it possible to randomly remove an element from vector< vector<short> >?
Below is a Sudoku initializer, I am attempting to create a function that based on User input, erases a random element from the the board. The random element can be removed from any part of the board. class cell{ bool m_occu; //occupied is shown '.' int m_num; public: cell() : m_occu(false), m_num(0) {} void setMark(const int num){m_num = num; m_occu = true;} bool isMarked() const { return m_occu; } int getNum(){ return m_num;} friend ostream& operator << (ostream& o, const cell& c){ if (!c.m_occu) return o << setw(2) << '-'; return o << setw(2) << c.m_num; } }; class board { vector<vector <cell> >m_map; bool col_row; public: board() { vector<cell> a_row(9); col_row = false; for (int i = 0; i < 9; ++i) { for(int j = 0; j < 9; j++) { a_row[j].setMark(j+1); } random_shuffle(a_row.begin(), a_row.end()); m_map.push_back(a_row); } } void erase(){ }
Here is the code for erase function: void erase(std::vector your_vector){ your_vector.erase(your_vector.begin() + random(1,your_vector.size())); } and this the code for random number generation: int random(int min, int max) //range(min, max) { bool first = true; if ( first ) { srand(time(NULL)); //seeding only for the first time first = false; } return min + rand() % (max - min); }
Saving local variables - Java
Here is a program that is supposed to find out whether a sequence of numbers match the mathematical formula a[n+1] = a[n]*b+c for any combination of b and c in the integer range -9:9. import java.util.Scanner; public class Nastaord{ private static int[] lasTal(){ int[] tallista; //Det vi ska ha talföljden i int i = 0; //räknare för tallista while(true){ System.out.print("Ange tal, eller tryck enter om du är klar: "); int nytt_tal = scanner.nextLine(); if(nytt_tal == ""){ return tallista;} tallista[i] = nytt_tal; i++; } } private static boolean bcFinns(int[] tallista){ boolean OK = true; for(int b = -9; b <= 9; b++){ for(int c = -9; c <= 9; c++){ for(int i = tallista.length; i > 0;i--){ OK = tallista[i] == tallista[i-1]*b+c; if(OK == false){ break;} } if(OK == true){ public int b = b; public int c = c; return true;} } } return false; } public static void main(String[] args){ boolean OK = bcFinns(lasTal()); if (OK == true){ System.out.print(tallista[tallista.length-1]*b+c); } if (OK == false){ System.out.print("No"); } } } The program, on a principal level, works. The only thing is that I do not know how to save the correct numbers b and c for the sequence once they are found. I tried creating two public variables so that I can access them in the main method, but I get the following error: Nastaord.java:30: error: illegal start of expression public int b = b; ^ Nastaord.java:31: error: illegal start of expression public int c = c; Could you help me save these variables b and c in some way?
public class Nastaord{ public static int bFinal,cFinal; Then later on: bFinal = b; cFinal = c;
Make sort using delegates
I'm try to make a sort delegate in C++/CLI, but, when I try to compile I recive this erro: >app.cpp(256): error C3374: can't take address of 'Program::AnonymousMethod1' unless creating delegate instance >app.cpp(256): error C2664: 'void System::Collections::Generic::List<T>::Sort(System::Comparison<T> ^)' : cannot convert parameter 1 from 'System::Object ^(__clrcall *)(Program::teste1,Program::teste1)' to 'System::Comparison<T> ^' > with > [ > T=Program::teste1 ^ > ] > No user-defined-conversion operator available, or > There is no context in which this conversion is possible ========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ========== here is the code sample of the error: using namespace System; using namespace System::Collections::Generic; private ref class Program { private: enum class tokens { teste, lala, blabla, }; ref struct teste1 { int linha; tokens tk; }; private: static Object ^AnonymousMethod1(teste1 p1, teste1 p2) { return p1.tk.CompareTo(p2.tk); } public: Program() { bool jump = false; List<teste1^>^ lstTest = gcnew List<teste1^>(); Random ^rnd = gcnew Random(); for (int i = 0; i < 20; i++) { teste1 ^tst = gcnew teste1(); switch (rnd->Next(1,4)) { case 1: tst->tk = tokens::teste; break; case 2: tst->tk = tokens::lala; break; case 3: tst->tk = tokens::blabla; break; } lstTest->Add(tst); } for each (teste1^ content in lstTest) { Console::WriteLine(content->tk.ToString()); } lstTest->Sort(AnonymousMethod1); Console::WriteLine("=============================================================="); for each (teste1^ content in lstTest) { Console::WriteLine(content->tk.ToString()); } } }; int main(array<String^> ^args) { Program^ prg = gcnew Program(); return 0; } I just whant to sort the list with the token 'lala' first, how I can make this, and, How I can solve this ???
Your List is of type List<test1^> (notice the ^ hat). So the Comparison<T> delegate you want is Comparison<teste1^>. Thus you'll want to change your AnonymousMethod1 as follows: static int AnonymousMethod1(teste1 ^ p1, teste1 ^ p2) { return p1->tk.CompareTo(p2->tk); } And in C++/CLI you need to explicitly create your delegate: Comparison<teste1 ^> ^ comparisonDelegate = gcnew Comparison<teste1 ^>(&AnonymousMethod1); lstTest->Sort(comparisonDelegate);
CUDA Thrust sort_by_key when the key is a tuple dealt with by zip_iterator's with custom comparison predicate
I've looked through a lot of questions here for something similar and there are quite a few, albeit with one minor change. I'm trying to sort values with a zip_iterator as a compound key. Specifically, I have the following function: void thrustSort( unsigned int * primaryKey, float * secondaryKey, unsigned int * values, unsigned int numberOfPoints) { thrust::device_ptr dev_ptr_pkey = thrust::device_pointer_cast(primaryKey); thrust::device_ptr dev_ptr_skey = thrust::device_pointer_cast(secondaryKey); thrust::device_ptr dev_ptr_values = thrust::device_pointer_cast(values); thrust::tuple,thrust::device_ptr> keytup_begin = thrust::make_tuple,thrust::device_ptr>(dev_ptr_pkey, dev_ptr_skey); thrust::zip_iterator, thrust::device_ptr > > first = thrust::make_zip_iterator, thrust::device_ptr > >(keytup_begin); thrust::sort_by_key(first, first + numberOfPoints, dev_ptr_values, ZipComparator()); } and this custom predicate: typedef thrust::device_ptr<unsigned int> tdp_uint ; typedef thrust::device_ptr<float> tdp_float ; typedef thrust::tuple<tdp_uint, tdp_float> tdp_uif_tuple ; struct ZipComparator { __host__ __device__ inline bool operator() (const tdp_uif_tuple &a, const tdp_uif_tuple &b) { if(a.head < b.head) return true; if(a.head == b.head) return a.tail < b.tail; return false; } }; The errors I'm getting are: Error 1 error : no instance of constructor "thrust::device_ptr::device_ptr [with T=unsigned int]" matches the argument list C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v4.0\include\thrust\detail\tuple.inl 309 1 --- Error 2 error : no instance of constructor "thrust::device_ptr::device_ptr [with T=float]" matches the argument list C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v4.0\include\thrust\detail\tuple.inl 401 1 --- Any ideas what might cause this / how do I write a predicate that indeed works? Thanks in Advance, Nathan
The comparator takes arguments of type const thrust::tuple<unsigned int, float>&. The const tdp_uif_tuple& type you defined expands to const thrust::tuple<thrust::device_ptr<unsigned int>, thrust:device_ptr<float> >& The code below compiles for me: struct ZipComparator { __host__ __device__ inline bool operator() (const thrust::tuple<unsigned int, float> &a, const thrust::tuple<unsigned int, float> &b) { if(a.head < b.head) return true; if(a.head == b.head) return a.tail < b.tail; return false; } }; Hope it does for you as well :) http://code.google.com/p/thrust/wiki/QuickStartGuide#zip_iterator has more details on the zip iterator. Not required, but if you're looking to clean up the length of those templates, you can do this: void thrustSort( unsigned int * primaryKey, float * secondaryKey, unsigned int * values, unsigned int numberOfPoints) { tdp_uint dev_ptr_pkey(primaryKey); tdp_float dev_ptr_skey(secondaryKey); tdp_uint dev_ptr_values(values); thrust::tuple<tdp_uint, tdp_float> keytup_begin = thrust::make_tuple(dev_ptr_pkey, dev_ptr_skey); thrust::zip_iterator<thrust::tuple<tdp_uint, tdp_float> > first = thrust::make_zip_iterator(keytup_begin); thrust::sort_by_key(first, first + numberOfPoints, dev_ptr_values, ZipComparator()); } A lot of the template arguments can be inferred from the arguments.
This is a fully worked example on how using sort_by_key when the key is a tuple dealt with by zip_iterator's and a customized comparison operator. #include <thrust/device_vector.h> #include <thrust/sort.h> #include "Utilities.cuh" // --- Defining tuple type typedef thrust::tuple<int, int> Tuple; /**************************/ /* TUPLE ORDERING FUNCTOR */ /**************************/ struct TupleComp { __host__ __device__ bool operator()(const Tuple& t1, const Tuple& t2) { if (t1.get<0>() < t2.get<0>()) return true; if (t1.get<0>() > t2.get<0>()) return false; return t1.get<1>() < t2.get<1>(); } }; /********/ /* MAIN */ /********/ int main() { const int N = 8; // --- Keys and values on the host: allocation and definition int h_keys1[N] = { 1, 3, 3, 3, 2, 3, 2, 1 }; int h_keys2[N] = { 1, 5, 3, 8, 2, 8, 1, 1 }; float h_values[N] = { 0.3, 5.1, 3.2, -0.08, 2.1, 5.2, 1.1, 0.01}; printf("\n\n"); printf("Original\n"); for (int i = 0; i < N; i++) { printf("%i %i %f\n", h_keys1[i], h_keys2[i], h_values[i]); } // --- Keys and values on the device: allocation int *d_keys1; gpuErrchk(cudaMalloc(&d_keys1, N * sizeof(int))); int *d_keys2; gpuErrchk(cudaMalloc(&d_keys2, N * sizeof(int))); float *d_values; gpuErrchk(cudaMalloc(&d_values, N * sizeof(float))); // --- Keys and values: host -> device gpuErrchk(cudaMemcpy(d_keys1, h_keys1, N * sizeof(int), cudaMemcpyHostToDevice)); gpuErrchk(cudaMemcpy(d_keys2, h_keys2, N * sizeof(int), cudaMemcpyHostToDevice)); gpuErrchk(cudaMemcpy(d_values, h_values, N * sizeof(float), cudaMemcpyHostToDevice)); // --- From raw pointers to device_ptr thrust::device_ptr<int> dev_ptr_keys1 = thrust::device_pointer_cast(d_keys1); thrust::device_ptr<int> dev_ptr_keys2 = thrust::device_pointer_cast(d_keys2); thrust::device_ptr<float> dev_ptr_values = thrust::device_pointer_cast(d_values); // --- Declare outputs thrust::device_vector<float> d_values_output(N); thrust::device_vector<Tuple> d_keys_output(N); auto begin_keys = thrust::make_zip_iterator(thrust::make_tuple(dev_ptr_keys1, dev_ptr_keys2)); auto end_keys = thrust::make_zip_iterator(thrust::make_tuple(dev_ptr_keys1 + N, dev_ptr_keys2 + N)); thrust::sort_by_key(begin_keys, end_keys, dev_ptr_values, TupleComp()); int *h_keys1_output = (int *)malloc(N * sizeof(int)); int *h_keys2_output = (int *)malloc(N * sizeof(int)); float *h_values_output = (float *)malloc(N * sizeof(float)); gpuErrchk(cudaMemcpy(h_keys1_output, d_keys1, N * sizeof(int), cudaMemcpyDeviceToHost)); gpuErrchk(cudaMemcpy(h_keys2_output, d_keys2, N * sizeof(int), cudaMemcpyDeviceToHost)); gpuErrchk(cudaMemcpy(h_values_output, d_values, N * sizeof(float), cudaMemcpyDeviceToHost)); printf("\n\n"); printf("Ordered\n"); for (int i = 0; i < N; i++) { printf("%i %i %f\n", h_keys1_output[i], h_keys2_output[i], h_values_output[i]); } }