Хорошо, я учел все, что вы сказали, и я отделил алгоритмы от спецификации. Имитируя STL, алгоритмы работают с итераторами; в то время как MyClass запрашивает спецификацию, инкапсулирует знание предметной области.
Как это выглядит для вас, ребята?
сначала отключите алгоритм:
/*
MyLib
---------------
Methods:
countOccurances()
- given the iterator pairs for two either contiguous areas of memory or containers
- counts the number of times the second (needle) occurs in the first (haystack)
- returns the count
replaceOccurances()
- same as countOccurances except when a sequence has been matched it is replaced
by the replacement needle which must be the same length
*/
template<class fwdIt>
size_t countOccurances(fwdIt haystackFront, fwdIt haystackEnd,
fwdIt needleFront, fwdIt needleEnd)
{
size_t lengthOfNeedle = std::distance(needleFront,needleEnd);
size_t lengthOfHaystack = std::distance(haystackFront,haystackEnd);
size_t count = 0;
while(true)
{
//find the needle
fwdIt tempIT1 = haystackFront, tempIT2 = needleFront;
while(true)
{
if(tempIT2 == needleEnd)
{
haystackFront += lengthOfNeedle;
lengthOfHaystack -= lengthOfNeedle;
count++;
break;
}
else if(*tempIT1 != *tempIT2)
{
break;
}
tempIT1++; tempIT2++;
}
if(lengthOfNeedle <= lengthOfHaystack)
{
++haystackFront;
--lengthOfHaystack;
}
else
{
break;
}
}
return count;
}
template<class fwdIt>
size_t replaceOccurances(fwdIt haystackFront, fwdIt haystackEnd,
fwdIt needleFront, fwdIt needleEnd,
fwdIt replacementFront, fwdIt replacementEnd)
{
//The needle and its replacement must be the same length,
//this method cannot be reponsible for growing a container it doesn't own.
if(std::distance(needleFront, needleEnd) != std::distance(replacementFront, replacementEnd))
throw exception("The needle and its replacement are not the same length");
size_t lengthOfNeedle = std::distance(needleFront,needleEnd);
size_t lengthOfHaystack = std::distance(haystackFront,haystackEnd);
size_t count = 0;
while(true)
{
//find the needle
fwdIt tempIT1 = haystackFront, tempIT2 = needleFront;
while(true)
{
if(tempIT2 == needleEnd)
{
//replace the needle
for(fwdIt tempIT3 = replacementFront;
haystackFront != tempIT1, tempIT3 != replacementEnd;
haystackFront++, tempIT3++)
{
*haystackFront = *tempIT3;
}
count++;
break;
}
else if(*tempIT1 != *tempIT2)
{
break;
}
tempIT1++; tempIT2++;
}
if(lengthOfNeedle <= lengthOfHaystack)
{
++haystackFront;
--lengthOfHaystack;
}
else
{
break;
}
}
return count;
}
и теперь MyClass
class MyClass
{
public:
static size_t getMyCount(std::string& sInput);
static size_t getMyCount(std::wstring& sInput);
static size_t replaceMyWithMY(std::string& sInput);
static size_t replaceMyWithMY(std::wstring& sInput);
protected:
static std::string _narrowNeedle;
static std::wstring _wideNeedle;
static std::string _narrowReplacementNeedle;
static std::wstring _wideReplacementNeedle;
template<class T>
static size_t _PerformStringOperation(T& sInput, T& sNeedle, bool replace = false, T& sReplacementNeedle = T())
{
try
{
if(replace)
{
return replaceOccurances( sInput.begin(), sInput.end(),
sNeedle.begin(), sNeedle.end(),
sReplacementNeedle.begin(), sReplacementNeedle.end());
}
else
{
return countOccurances( sInput.begin(), sInput.end(),
sNeedle.begin(), sNeedle.end());
}
}
catch(MYException& e)
{
clog << "MyClass::_PerformStringOperation() - could not perform operation" << endl;
clog << e.what();
throw;
}
catch(exception& e)
{
clog << "MyClass::_PerformStringOperation() - Something more fundemental went wrong" << endl;
clog << e.what();
throw;
}
}
};
и сопровождающий CPP
std::string MyClass::_narrowNeedle("My");
std::wstring MyClass::_wideNeedle = std::wstring(L"My");
std::string MyClass::_narrowReplacementNeedle = std::string("MY");
std::wstring MyClass::_wideReplacementNeedle = std::wstring(L"MY");
size_t MyClass::getNiCount(std::string& sInput)
{
try
{
return _PerformStringOperation(sInput,_narrowNeedle);
}
catch(...)
{
throw;
}
}
size_t MyClass::getNiCount(std::wstring& sInput)
{
try
{
return _PerformStringOperation(sInput,_wideNeedle);
}
catch(...)
{
throw;
}
}
size_t MyClass::replaceNiWith(std::string& sInput)
{
try
{
return _PerformStringOperation(sInput,_narrowNeedle,true,_narrowReplacementNeedle);
}
catch(...)
{
throw;
}
}
size_t MyClass::replaceNiWith(std::wstring& sInput)
{
try
{
return _PerformStringOperation(sInput,_wideNeedle,true,_wideReplacementNeedle);
}
catch(...)
{
throw;
}
}