Sign in to follow this  
Mybowlcut

[C++] What's better?

Recommended Posts

Mybowlcut    176
[size="2"]GameDev source tags are crappy, so I have to use pastebin: [url="http://pastebin.com/GZkbihzY"]http://pastebin.com/GZkbihzY[/url][/size]

Which is more efficient if the input is a string?

Share this post


Link to post
Share on other sites
Aardvajk    13207
GameDev source tags are almost identical:

[source lang="cpp"]
template<typename T>
std::string to_string(const T& t)
{
std::ostringstream oss;
oss << std::dec << t;
return oss.str();
}

template<typename T>
std::string to_string(const T& t)
{
if(!boost::is_base_and_derived<std::string, T>::value)
{
std::ostringstream oss;
oss << std::dec << t;
return oss.str();
}
return t;
}
[/source]

I'd say neither, a specialization for std::string would resolve at compile time. Since you are not supposed to derive from std::string, the following should be safe.

[source lang="cpp"]
template<>
std::string to_string<std::string>(const std::string &t)
{
return t;
}
[/source]

You could also specialize for const char* to do a direct std::string construction and skip the need for a stringstream.

Or you could just use [url="http://www.google.co.uk/search?sourceid=chrome&ie=UTF-8&q=boost%3A%3Alexical_cast"]boost::lexical_cast[/url]? Not sure, never used it but I understand it does the same thing.

Share this post


Link to post
Share on other sites
Mybowlcut    176
[quote name='Aardvajk' timestamp='1307529235' post='4820875']
GameDev source tags are almost identical:

[source lang="cpp"]
template<typename T>
std::string to_string(const T& t)
{
std::ostringstream oss;
oss << std::dec << t;
return oss.str();
}

template<typename T>
std::string to_string(const T& t)
{
if(!boost::is_base_and_derived<std::string, T>::value)
{
std::ostringstream oss;
oss << std::dec << t;
return oss.str();
}
return t;
}
[/source]

I'd say neither, a specialization for std::string would resolve at compile time. Since you are not supposed to derive from std::string, the following should be safe.

[source lang="cpp"]
template<>
std::string to_string<std::string>(const std::string &t)
{
return t;
}
[/source]

You could also specialize for const char* to do a direct std::string construction and skip the need for a stringstream.

Or you could just use [url="http://www.google.co.uk/search?sourceid=chrome&ie=UTF-8&q=boost%3A%3Alexical_cast"]boost::lexical_cast[/url]? Not sure, never used it but I understand it does the same thing.
[/quote]
When I was using the source tags, they didn't resolve to a code snippet, instead produced a bunch of HTML.

I hadn't thought about specialisation, cheers. :)

Edit: That won't work... it seems that unless I pass std::string as a template argument, it won't use the specialised function...

Share this post


Link to post
Share on other sites
Aardvajk    13207
The following, compiled with g++:

[source lang="cpp"]
#include <iostream>

template<class T> void test(const T &t)
{
std::cout << "general\n";
}

template<> void test<std::string>(const std::string &t)
{
std::cout << "specialized\n";
}

int main()
{
std::string s="hello";

test(s);
test(23);
}
[/source]

Produces the output:

[code]
general
specialized
[/code]

I can't figure out how to specialize for const char* though, as a literal string will call the general version, but I cannot specialize for const char* as it errors saying it does not match any template.

Template gurus to the rescue?

(BTW, new source tags are [ source lang="cpp" ] without spaces).

Share this post


Link to post
Share on other sites
Aardvajk    13207
Weird. Using VC10, the following has the same error:

[source lang="cpp"]

class x
{

template<class T> void test(const T &t) const
{
std::cout << "general\n";
}

template<> void test<std::string>(const std::string &t) const
{
std::cout << "specialized\n";
}

template<> void test<char*>(char *s) const
{
std::cout << "specialized for char*\n";
}

};
[/source]

But some old library code of mine compiles fine:

[source lang="cpp"]
class xcs::node
{
public:
/* snip */

template<class T> bool is() const;
template<> bool is<std::string>() const { return true; }

template<> bool is<char*>() const { return false; }
template<> bool is<const char*>() const { return false; }

/* snip */
};
[/source]

Buggered if I can see what the difference is.

Share this post


Link to post
Share on other sites
Mybowlcut    176
[quote name='Aardvajk' timestamp='1307532097' post='4820888']
The following, compiled with g++:

[source lang="cpp"]
#include <iostream>

template<class T> void test(const T &t)
{
std::cout << "general\n";
}

template<> void test<std::string>(const std::string &t)
{
std::cout << "specialized\n";
}

int main()
{
std::string s="hello";

test(s);
test(23);
}
[/source]

Produces the output:

[code]
general
specialized
[/code]

I can't figure out how to specialize for const char* though, as a literal string will call the general version, but I cannot specialize for const char* as it errors saying it does not match any template.

Template gurus to the rescue?

(BTW, new source tags are [ source lang="cpp" ] without spaces).
[/quote]
I was just using [source][/source]... perhaps I had some subtle typo.

And you're right, that works perfectly, I mustn't have made the correct changes to my code to test it out. :x Full of mistakes today!

[quote name='rip-off' timestamp='1307532428' post='4820893']
is_base_and_derived - you shouldn't be deriving from std::string. Are you?
[/quote]
No way! Haha! No, I just wanted a nice way to determine the type of an object - have no idea if that was the correct way, but from my googling it seemed like it would do the job.

Share this post


Link to post
Share on other sites
Mybowlcut    176
Hmm... I seem to be getting linker warnings from these functions:

[source lang="cpp"]template<typename T>
std::string to_string(const T& t, std::ios_base& (*f)(std::ios_base&))
{
std::ostringstream oss;
oss << f << t;
return oss.str();
}

// Uses std::dec.
template<typename T>
std::string to_string(const T& t)
{
std::ostringstream oss;
oss << std::dec << t;
return oss.str();
}

// Specialised version that doesn't do any conversion.
template<>
std::string to_string<std::string>(const std::string& t)
{
return t;
}[/source]

[quote]Warning 5 warning LNK4006: "class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl Conversions::to_string<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (??$to_string@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Conversions@@YA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@ABV12@@Z) already defined in Triggered_Animation.obj; second definition ignored Toolbar.obj

etc...[/quote]

Share this post


Link to post
Share on other sites
Hodgman    51328
You need to inline the specialized version, as it's not really a template any more.

BTW, you don't even need template specialization here -- regular overloads will do:[code] template<typename T> std::string to_string(const T& t)
{
std::ostringstream oss;
oss << std::dec << t;
return oss.str();
}
inline std::string to_string(const std::string& t)
{
return t;
}
inline std::string to_string(const char* t)
{
return t;
}[/code]

Share this post


Link to post
Share on other sites
Aardvajk    13207
Hidden
Hodgman's on the money. The following produces the expected results:

[source lang="cpp"]
#include <iostream>

template<class T> void test(const T &t)
{
std::cout << "general\n";
}

void test(const std::string &t)
{
std::cout << "specialized\n";
}

void test(const char *s)
{
std::cout << "specialized (literal)\n";
}

int main()
{
std::string s="hello";

test(s);
test(23);
test("hahah");
}
[/source]

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this