Loki TypeTraits and compilation problems

K

Krivenok Dmitry

I writing simple class CmdLine:
.....
.....
class CmdLine
{
.....
.....
public:
/// Constructor
CmdLine(int argc, char** argv);
/// Destructor
~CmdLine();

template <class T>
void GetOption (const std::string& OptionName, T& OptionVar) const
{
if ( Loki::TypeTraits<T>::isStdIntegral )
{
std::cout << "bool\n"; //For debug
OptionVar = BoolOptions_.find(OptionName)->second;
}
else
{
std::cout << "string\n"; //for debug
OptionVar = StringOptions_.find(OptionName)->second;
}
}
private:
/// Map for string options, e.g. Script File Name
std::map<std::string,std::string> StringOptions_;
/// Map for bool options, e.g. Disable StdErr Output
std::map<std::string,bool> BoolOptions_;
....
....
};
.....
.....

I use TypeTraits from Loki Library by A. Alexandrescu to determine
types class (integral or not).
If type is integral (e.g. bool), then I use BoolOptions_ map. Else
I use StringOptions_ map.

My main function :
#include <string>
#include <iostream>
#include "Cmdline.hpp"
#include "Cfg.h"

using namespace std;

int main( int argc, char* argv[] )
{
CmdLine CC(argc,argv);
bool b;
std::string s;
CC.GetOption("str_opt",s);
CC.GetOption("bool_opt",b);
return 0;
}

But my code doesn't compile!
Errors are :

CmdLineParse/Cmdline.hpp: In member function `void
CmdLine::GetOption(const
std::string&, T&) const [with T = bool]':
Application/Application.cpp:20: instantiated from here
CmdLineParse/Cmdline.hpp:52: cannot convert `const std::string' to
`bool' in
assignment

But if I comment assigments (OptionVar = ...), then my code compile
succ
and output is:
string
bool

In this case used valid branch of 'if' statment.

Why my code doesn't compile if first case???
 
M

mlimber

Krivenok said:
I writing simple class CmdLine:
....
....
class CmdLine
{
.....
.....
public:
/// Constructor
CmdLine(int argc, char** argv);
/// Destructor
~CmdLine();

template <class T>
void GetOption (const std::string& OptionName, T& OptionVar) const
{
if ( Loki::TypeTraits<T>::isStdIntegral )
{
std::cout << "bool\n"; //For debug
OptionVar = BoolOptions_.find(OptionName)->second;
}
else
{
std::cout << "string\n"; //for debug
OptionVar = StringOptions_.find(OptionName)->second;
}
}
private:
/// Map for string options, e.g. Script File Name
std::map<std::string,std::string> StringOptions_;
/// Map for bool options, e.g. Disable StdErr Output
std::map<std::string,bool> BoolOptions_;
....
....
};
....
....

I use TypeTraits from Loki Library by A. Alexandrescu to determine
types class (integral or not).
If type is integral (e.g. bool), then I use BoolOptions_ map. Else
I use StringOptions_ map.

My main function :
#include <string>
#include <iostream>
#include "Cmdline.hpp"
#include "Cfg.h"

using namespace std;

int main( int argc, char* argv[] )
{
CmdLine CC(argc,argv);
bool b;
std::string s;
CC.GetOption("str_opt",s);
CC.GetOption("bool_opt",b);
return 0;
}

But my code doesn't compile!
Errors are :

CmdLineParse/Cmdline.hpp: In member function `void
CmdLine::GetOption(const
std::string&, T&) const [with T = bool]':
Application/Application.cpp:20: instantiated from here
CmdLineParse/Cmdline.hpp:52: cannot convert `const std::string' to
`bool' in
assignment

But if I comment assigments (OptionVar = ...), then my code compile
succ
and output is:
string
bool

In this case used valid branch of 'if' statment.

Why my code doesn't compile if first case???

It's because your function CmdLine::GetOption<>() is instantiated for a
type T (in this case either bool or std::string), but one of the two
assignments won't compile for T. That is, for T=bool your function is
instantiated as:

void GetOption (const std::string& OptionName, bool& OptionVar) const
{
if ( Loki::TypeTraits<T>::isStdIntegral )
{
std::cout << "bool\n"; //For debug
OptionVar = BoolOptions_.find(OptionName)->second;
// Ok: that's bool = bool.
}
else
{
std::cout << "string\n"; //for debug
OptionVar = StringOptions_.find(OptionName)->second;
// Error: that's bool = std::string!
}
}

And likewise for T=std::string. You could use partial template
specialization to do what you want:

template<typename T>
void GetOption( std::string const& OptionName, T& OptionVar ) const;

template<>
void CmdLine::GetOption<std::string>(
std::string const& OptionName,
std::string & OptionVar ) const
{
std::cout << "string\n"; //for debug
OptionVar = StringOptions_.find(OptionName)->second;
}

template<>
void CmdLine::GetOption<bool>(
std::string const& OptionName,
bool& OptionVar ) const
{
std::cout << "bool\n"; //For debug
OptionVar = BoolOptions_.find(OptionName)->second;
}

Also, you may want to consider using Boost's type traits instead of
Loki's. They do essentially the same task, but the former is more
widely tested and are part of TR1, which will likely become part of the
C++ standard library soon (see
http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1745.pdf).

Cheers! --M
 
K

Krivenok Dmitry

I read Modern C++ Design (2.10.5)
and write this code:

enum MapSelector {Integral, String};

template <class T>
void GetOptionImpl (const std::string& OptionName, T&
OptionVar,Loki::Int2Type<Integral>) const
{
std::cout << "bool\n";
OptionVar = BoolOptions_.find(OptionName)->second;
}

template <class T>
void GetOptionImpl (const std::string& OptionName, T&
OptionVar,Loki::Int2Type<String>) const
{
std::cout << "string\n";
OptionVar = StringOptions_.find(OptionName)->second;
}

template <class T>
void GetOption (const std::string& OptionName, T& OptionVar) const
{
enum {MapType = Loki::TypeTraits<T>::isStdIntegral ? Integral :
String };
// Problem line (*)
GetOptionImpl(OptionName, OptionVar, Loki::Int2Type<MapType>);
}

But compilation is not succ again!
Errors are:
In file included from CmdLineParse/Cmdline.cpp:7:
CmdLineParse/Cmdline.hpp: In member function `void
CmdLine::GetOption(const
std::string&, T&) const':
CmdLineParse/Cmdline.hpp:59: syntax error before `;' token

Line 59 = Problem line (*)
 
M

mlimber

Krivenok said:
I read Modern C++ Design (2.10.5)
and write this code:

enum MapSelector {Integral, String};

template <class T>
void GetOptionImpl (const std::string& OptionName, T&
OptionVar,Loki::Int2Type<Integral>) const
{
std::cout << "bool\n";
OptionVar = BoolOptions_.find(OptionName)->second;
}

template <class T>
void GetOptionImpl (const std::string& OptionName, T&
OptionVar,Loki::Int2Type<String>) const
{
std::cout << "string\n";
OptionVar = StringOptions_.find(OptionName)->second;
}

template <class T>
void GetOption (const std::string& OptionName, T& OptionVar) const
{
enum {MapType = Loki::TypeTraits<T>::isStdIntegral ? Integral :
String };
// Problem line (*)
GetOptionImpl(OptionName, OptionVar, Loki::Int2Type<MapType>);
}

But compilation is not succ again!
Errors are:
In file included from CmdLineParse/Cmdline.cpp:7:
CmdLineParse/Cmdline.hpp: In member function `void
CmdLine::GetOption(const
std::string&, T&) const':
CmdLineParse/Cmdline.hpp:59: syntax error before `;' token

Line 59 = Problem line (*)

See my previous post for an alternate solution that is easier to read
IMHO, but I think you need to create an Int2Type<> object on your
problem line:

GetOptionImpl(OptionName, OptionVar, Loki::Int2Type<MapType>() );

Cheers! --M
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top