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]);
}
}