GameDev source tags are crappy, so I have to use pastebin: http://pastebin.com/GZkbihzY
Which is more efficient if the input is a string?
[C++] What's better?
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 boost::lexical_cast? Not sure, never used it but I understand it does the same thing.
[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 boost::lexical_cast? Not sure, never used it but I understand it does the same thing.
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 boost::lexical_cast? Not sure, never used it but I understand it does the same thing.
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...
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:
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).
[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:
general
specialized
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).
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.
[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.
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:
general
specialized
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).
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!
is_base_and_derived - you shouldn't be deriving from std::string. Are you?
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.
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]
[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]
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]
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:
BTW, you don't even need template specialization here -- regular overloads will do:
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;
}
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement