Re: templates - method return value is multiple types
On 5/27/2011 1:45 PM, Christopher wrote:
Is it possible to create a method that can return different types
using a template?
You did.
My goal is to get a value from the Window's Registry in one handy
dandy place. However my question is on template methods, not the
WIndows API.
OK.
I suppose I could split this up into one private method and two public
ones,
Why two?
> having the private method get a string and the public ones
taking an [out] reference to a string, while the other take an [out]
reference to an int.
Why a reference? Functions should return values.
> I'd rather figure out if I can handle it in one
method though. I don't use templates much, so I figured this is an
opportunity to learn more.
I read that the compiler generates code based on the T, so I suppose
the errors I am getting make sense about "return cannot convert from _
to_" and makes me believe what I want here cannot be done with
templates, but I want to be sure there isn't another way using
templates.
You don't show how you use your function. Please do.
Here is what I tried initially:
class RegistrySettings
{
public:
/// The one and only registry key for the .....
static const std::wstring MYCOMPONENT_REG_KEY;
~RegistrySettings();
static const RegistrySettings * Instance();
template<typename T>
const T GetValue(const std::wstring& valueName) const
{
HKEY registryKey = NULL;
DWORD disposition = 0;
if( ERROR_SUCCESS != RegCreateKeyEx(HKEY_LOCAL_MACHINE,
RegistrySettings::MYCOMPONENT_REG_KEY.c_str(),
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
®istryKey,
&disposition) )
{
// Unexpected error
}
boost::scoped_array<TCHAR> buffer;
DWORD bufferSize = (MAX_PATH / 2) *
sizeof(TCHAR);
DWORD type = 0;
DWORD result = 0;
do
{
bufferSize *= 2;
buffer.reset(new TCHAR[bufferSize]);
result = RegQueryValueEx(registryKey,
valueName.c_str(),
NULL,
&type,
reinterpret_cast<BYTE
*>(buffer.get()),
&bufferSize);
}while(result == ERROR_MORE_DATA);
if( result != ERROR_SUCCESS )
{
// Unexpected Error
}
if( ERROR_SUCCESS != RegCloseKey(registryKey) )
{
// Unexpected Error
}
switch(type)
{
case REG_DWORD:
return boost::lexical_cast<DWORD>(buffer.get());
case REG_SZ:
return std::wstring(buffer.get());
case REG_EXPAND_SZ:
boost::scoped_array<TCHAR> expandedBuffer;
DWORD expandedBufferSize =
(MAX_PATH / 2) * sizeof(TCHAR);
DWORD characterCount = 0;
characterCount =
ExpandEnvironmentStrings(buffer.get(),
expandedBuffer.get(),
expandedBufferSize);
while( characterCount> expandedBufferSize )
{
// Buffer was too small, retry
// TODO - TEST THIS for infinite loop!!!
expandedBufferSize = characterCount;
expandedBuffer.reset(new
TCHAR[expandedBufferSize]);
characterCount =
ExpandEnvironmentStrings(buffer.get(),
expandedBuffer.get(),
expandedBufferSize);
}
if( !characterCount )
{
// Unexpected Error
}
return std::wstring(expandedBuffer.get());
default:
throw common::NotImplementedException(__WFILE__,
__LINE__)<< L"The registry value type cannot be converted."<<
valueName;
}
}
private:
RegistrySettings();
RegistrySettings(const RegistrySettings& rhs);
static const RegistrySettings * m_instance;
};
}
#endif // REGISTRY_STRINGS
^^^^^^ What does this '#endif' close? I don't see an #ifxxx
I don't see the complete code. See FAQ 5.8.
V
--
I do not respond to top-posted replies, please don't ask