|
Hi All!
Here goes the question:
Mr. C++ has cleary descibed how to use function objects in Parhagraph 18.4 of his Book. The
Sample code works OK, and if i use them with STL, everything`s OK
Here is a simple sample:
void Add7(int& out_Int)
{
out_Int += 7;
}
class AddNumber
{
public:
int m_iToAdd;
AddNumber(int in_iToAdd = 0)
{
m_iToAdd = in_iToAdd;
}
void operator()(int& out_Int)
{
out_Int += m_iToAdd;
}
};
class A
{
public:
std::vector < int > m_vData;
};
void main()
{
A tmp_a;
tmp_a.m_vData.push_back(7);
tmp_a.m_vData.push_back(5);
tmp_a.m_vData.push_back(6);
std::for_each(tmp_a.m_vData.begin(),tmp_a.m_vData.end(),Add7);
std::for_each(tmp_a.m_vData.begin(),tmp_a.m_vData.end(),AddNumber(13));
}
---
But when i try to use them some other way than in combination with STL, I get that:
typedef void (*TraveseFuncPtr) (int&);
void Add7(int& out_Int)
{
out_Int += 7;
}
class AddNumber
{
public:
int m_iToAdd;
AddNumber(int in_iToAdd = 0)
{
m_iToAdd = in_iToAdd;
}
void operator()(int& out_Int)
{
out_Int += m_iToAdd;
}
};
class A
{
public:
std::vector < int > m_vData;
void TraverseVector(TraveseFuncPtr in_func)
{
for (int i = 0; i < m_vData.size(); i++)
{
(*in_func)(m_vData[i]);
}
}
};
void main()
{
A tmp_a;
tmp_a.m_vData.push_back(7);
tmp_a.m_vData.push_back(5);
tmp_a.m_vData.push_back(6);
tmp_a.TraverseVector(Add7); // All ok.
tmp_a.TraverseVector(AddNumber(13)); //C2664
}
---
And thats it.
error C2664: 'TraverseVector' : cannot convert parameter 1 from 'class AddNumber' to 'void (__cdecl *)(int &)'
No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
I tried to dig up STL source but hell the same for_each takes a CLASS (!) as a template parameter.
No functions there.
Who can say anything to this?
Sincerely yours, Ilya Kalujny.
|
|
|
|
|
Yes, but what you have defined as the argument to the TraverseVector is simplay a function pointer:
typedef void (*TraveseFuncPtr) (int&);
Function pionters are not quite the same thing as function objects. If you want to define a function that accepts as a parameter a functor (some class which has an overloaded operator()), then you could make the function a template function and have the exact type of the class you wold pass in a template parameter.
Maybe something like this:
template<class _functortype="">
void TraverseVector(_FunctorType in_func)
{
for (int i = 0; i < m_vData.size(); i++)
{
in_func(m_vData[i]);
}
}
This should allow you to pass in an aribtrary type as an argument, so long as it had an overloaded operator() with the correct signature.
|
|
|
|
|
One question:
Isn't a function object (also named Functor) an object which behaves like a function?.
That means this object has an overloaded operator() returning whatever the object does.
This could be the explanation why the STL wants a CLASS - it calls its operator().
For your Add7-Object it would look about like
class Add7()
{
int operator()(int& out_Int)const
{
return out_Int + 7;
};
} This can be further complicated by making the class Add7 a template.
My opinions may have changed, but not the fact that I am right.
|
|
|
|
|
One way to do what you want would be to make the traverse vector method a template method. I recommend against doing this, using STL means using all (or as much as you can manage) of it - so you should attempt to reuse tools like for_each wherever you can. for_each works along the same lines as the attached code, but may be optomised by the library for some template specialisations.
The problem, passing extra information to a functor (function object), that you're putting forward is quite common, binders are a good place to look if you're interested in more generic solutions to this problem.
class A <br />
{<br />
public:<br />
std::vector < int > m_vData;<br />
<br />
template<class F><br />
void TraverseVector(F in_func) <br />
{<br />
for (int i = 0; i < m_vData.size(); i++) <br />
{<br />
in_func(m_vData[i]);<br />
cout << m_vData[i] << endl;<br />
}<br />
}<br />
<br />
};
|
|
|
|
|
You are not passing a pointer to a function:
tmp_a.TraverseVector(AddNumber(13));
(passing the return value of AddNumber(13) to TraverseVector(), which is void/nothing/nada).
This is passing a pointer to a function:
tmp_a.TraverseVector(AddNumber);
Trust in the code Luke. Yea right!
|
|
|
|
|
the definition of std::for_each
template <class InputIterator, class Function>
Function for_each (InputIterator first, InputIterator last, Function f)
so, you can do this:
// =======================================================
class A
{
public:
std::vector <int> m_vData;
template <class Function> // add this
void TraverseVector(Function in_func) // ******
{
for (int i = 0; i < m_vData.size(); i++)
{
(*in_func)(m_vData[i]);
}
}
};
// =======================================================
|
|
|
|
|
I have an MDI application witn 2 document templates (with 1 or more child windows normally open). One child window is of one type while there can be multiple child windows of the other type.
I would like to have a common menu independant of the active child window. The problem I am facing is of updation of status of the menu (checked/ unchecked etc). Apparently, the menu displayed is that of the active child frame. Presently, I have the identical menu for both document types.
Is there any standard method to synchronize the menu for the both the frames?
Thanks
Jayanta Basu
|
|
|
|
|
hi all,
I want to write some data to a existing text file...I am using ATL...I dont have any clue..can anyone help and tell me how to proceed..any help or pointers are highly appreciated..
thanks in advance
Himanshu
|
|
|
|
|
std::ofstream outFile(szFilename, ios::out | ios::app);
outFile << "Your Text Here!";
outFile.close();
- Nitron
"Those that say a task is impossible shouldn't interrupt the ones who are doing it." - Chinese Proverb
|
|
|
|
|
I have a string containing the sentence: "a do cat from hello thomas d"
My task is to read through the string, determine what is the shortest word(s) and what is the longest word(s) then display each.
So for the sentence above, i will need to display the following:
Biggest word(s)= thomas
Smallest word(s) = a, d
The problem i have is determining the longest and shortest word(s).
This is my first attempt at C++ after Java for 6 months before i changed my course at college
Please help me
..::M::..
|
|
|
|
|
The simplest way to do it is to use the MFC CString class. It's much like the Java String.
Create a new project, choose MFC application, then dialog-based. From this point, you can use the MFC CString class.
|
|
|
|
|
Hi,
Try with following code snippet.
----------------------------------------------------------
CString strSentence = "a do cat from hello thomas d";
int iLongest = 0; //Initialize with minimum value.
int iShortest = 1024; //Initialize with Big Value
int nIndex;
//Backup. If you dont want you can remove
CString strHelper(strSentence);
while(!strHelper.IsEmpty())
{
if(-1 == (nIndex = strHelper.Find(' ', 0)))
{
nIndex = strHelper.GetLength(); //Last word
strHelper.Empty();
}
if(nIndex < iShortest)
iShortest = nIndex;
if(nIndex > iLongest)
iLongest = nIndex;
strHelper.Delete(0, nIndex+1); //Remove including space.
}
----------------------------------------------------------
|
|
|
|
|
Hi all,
in mfc dialog based application i have the following function.
void Reverse()
{
// TODO: Add your control notification handler code here
int nIndex, nStrLength, nWordIndex;
TCHAR *pStrWord, *pStrFinal, ch;
UpdateData(TRUE);
nStrLength = m_strInput.GetLength();
pStrWord = new TCHAR [nStrLength + 1];
pStrFinal = new TCHAR [nStrLength + 1];
*pStrWord = '\0';
*pStrFinal = '\0';
nWordIndex = 0;
for (nIndex = 0;nIndex < nStrLength; nIndex++)
{
ch = m_strInput.GetAt(nIndex);
if ( ch != ' ' || nIndex == nStrLength )
{
pStrWord[nWordIndex] = m_strInput.GetAt(nIndex);
nWordIndex++;
}
if ( ch == ' ' )
{
pStrWord[nWordIndex++] = ' ';
pStrWord[nWordIndex] = '\0';
_tcscat(pStrFinal,_tcsrev(pStrWord));
nWordIndex=0;
}
if ( nIndex == (nStrLength - 1) )
{
pStrWord[nWordIndex++] = ' ';
pStrWord[nWordIndex] = '\0';
_tcscat(pStrFinal,_tcsrev(pStrWord));
nWordIndex = 0;
}
}
pStrFinal = _tcsrev(pStrFinal);
pStrFinal[nStrLength] = '\0';
m_strOutput = pStrFinal;
UpdateData(FALSE);
delete [] pStrWord;
delete [] pStrFinal;
}
I get error when deleting pStrFinal could anyone tell me why this happens. can any one of you explain me how to dump memory and to verify it.
|
|
|
|
|
With pStrFinal = _tcsrev(pStrFinal); , you are messing your pointer away.
I recommend to use the MFC CString class instead (since you said it's a MFC dialog). This hides all this memory allocation mess.
|
|
|
|
|
Hi,
Regarding the technique of dumping in-memory statistics, is
given below
Note: memstate1 takes snapshot of pre-memory leak and
memstate2 takes snapshot of post-memory leak. finally,
memstate3 makes the statistics based on both the snapshots.
CMemoryState memState1, memState2, memState3;
void CHello::MakeMemoryLeak()
{
memState1.Checkpoint();
LPCTSTR strMemoryLeak = new char[50];
memState2.Checkpoint();
memState3.Difference(memState1, memState2);
memState3.DumpStatistics();
}
Hope this Helps
Regards
~Hari~
|
|
|
|
|
saravanaram wrote:
I get error when deleting pStrFinal...
So what's the error?
I suspect the problem lies within the following line, but can't know for sure without stepping through the code.
pStrFinal = _tcsrev(pStrFinal);
|
|
|
|
|
Hi David,
if you see the memory contents of (pStrWord), it contains
5 (CD - valid memory allocated) and 4 FD(padded memory, # may differ)
(Note: Assume that nStrLength is 5)
Following code lines, are writing on unallocated memory.
pStrWord[nWordIndex++] = ' '; //This causes the problem.
pStrWord[nWordIndex] = '\0';
_tcscat(pStrFinal,_tcsrev(pStrWord));
as well,
pStrFinal = _tcsrev(pStrFinal); //This assignment also causes the problem.
Actually, he has to allocate the extra one byte of memory to put the space character (' ').
Hopefully, I am right.
regards
~Hari~
|
|
|
|
|
|
Greetings. I'm using a VC++ 6.0 MDI to call a VC# form .dll. I exposed the VC# dll as a COM interface... n now I need to tell the VC# dll who's the daddy... but the VC# forms daddy should be a System.Windows.Forms.Form()... So i want to pass the handle of the VC++ 6.0 MDI app to a method from the VC#... it asks for an IUnknown... Please tell me how do i take the this->m_hWnd pass it through an IUnknow* and finally put it in a System.Windows.Forms.Form object... can this b done? is there a more friendly way? Thanks
NHM
|
|
|
|
|
If the only thing you need to pass is a window handle, then ::SendMessage(...) is probably the fastest way to achieve it. It does not require the COM interop you have mentioned.
|
|
|
|
|
how can the VC# dll receive messages... in vc++6.0 PreTranslateMessage is the answer... n in VC#?
|
|
|
|
|
NHM wrote:
how can the VC# dll receive messages... in vc++6.0 PreTranslateMessage is the answer... n in VC#?
A Windows Forms app has a UI thread which processes windows messages just like any WIN32 app with a message loop. Any Windows Form control has a virtual WndProc method that can be overridden to respond accordingly.
The other way, a C# app can send a WIN32 message to any window (for instance a window from a VC++6 app) by using the [DllImport] P/Invoke technique :
[DllImport("user32.dll", CharSet=CharSet.Auto)]
public static extern int SendMessage(IntPtr hWnd, int msg, int wParam, int lParam);
|
|
|
|
|
if i override WndProc in the windows form (C# dll) then when i try to open it through the VC++ 6.0 App it stops execution... just gives a runtime error... ideas? thanks 4 your suport .S.Rod!
|
|
|
|
|
NHM wrote:
when i try to open it through the VC++ 6.0 App
What do you mean ?
Has it anything to do with the debug session ? Do you mean you are trying to access the C# WndProc implementation from your VC++ debug session ? No need to go further, you simply can't.
Or do you mean you are processing the message in the C# wndproc implementation and then it fails? If the code fails at this point, then it might be helpful for those listening if you post the code.
|
|
|
|
|
i've just overriden the WndProc... no code added to the base override...
this is what i have...
a) a vc++ 6.0 Mdi app (.exe)
b) a vc# dll with:
- class A (interface) (cominterop)
(i have to call some methods and access some properties)
- class B (windows form)
in the vc++ 6.0 mdi app i create an instance of classA
then i call a method from class A wich does this:
public void SomeThing()
{
Form1 f = new Form1();
f.Show();
}
and this is what i intended to do:
public void SomeThing( Form parent)
{
Form1 f = new Form1( Form parent);
f.MdiParent = parent;
f.Show();
}
i just want to say to the VC# winForm that his container is the VC++ 6.0 APP
what can i do?
|
|
|
|