Template functions to check "is int"/"is double"/etc - c++

I am a bit shaky with C++ template syntax, so I'm not sure if what I'm envisioning is possible, and if it is, I'm unclear on correct syntax.
I would like to implement template functions like template<int> bool is( std::string& ), template<double> bool is( std::string& ), etc. so that I can call is <int> (...) or is <double> (...) instead of isInt(...) or isDouble(...), etc. Is this possible? If so, how would you code the function signatures?
With my tenuous grasp of template syntax, my attempt was:
#include <iostream>
#include <cstdlib>
template<int>
bool is( std::string& raw )
{
if ( raw.empty() ) return false;
char* p;
int num = strtol( raw.c_str(), &p, 10);
return ( ( *p != '\0' ) ? false : true );
}
int main( int argc, char* argv[] )
{
std::string str("42");
std::cout << std::boolalpha << is <int> ( str ) << std::endl;
return 0;
}
This failed with the following errors:
>g++ -g main.cpp
main.cpp: In function ‘int main(int, char**)’:
main.cpp:16:51: error: no matching function for call to ‘is(std::string&)’
std::cout << std::boolalpha << is <int> ( str ) << std::endl;
^
main.cpp:5:6: note: candidate: template<int <anonymous> > bool is(std::string&)
bool is( std::string& raw )
^
main.cpp:5:6: note: template argument deduction/substitution failed:

My comment to your post withstanding, the way to do this easily is with a simple template that uses the std::istringstream class to parse:
template<typename T>
bool is(std::string const& raw) {
std::istringstream parser(raw);
T t; parser >> t;
return !parser.fail() && parser.eof();
}
The obvious caveat is that T must be default constructable. But on the plus side, the above will work for user defined types as well, so long as they implement operator >>.

You need to use template specialisation for this:
#include <iostream>
#include <cstdlib>
template<class T> bool is(std::string& raw) = delete;
template<>
bool is<int>( std::string& raw )
{
if ( raw.empty() ) return false;
char* p;
int num = strtol( raw.c_str(), &p, 10);
return ( ( *p != '\0' ) ? false : true );
}
int main( int argc, char* argv[] )
{
std::string str("42");
std::cout << std::boolalpha << is <int> ( str ) << std::endl;
return 0;
}
You can read more about in here

Related

C++ change list while iterating?

In C++11 have a list called jobs, in which I want to delete all jobs with stopped flag being true, so I wrote:
auto job = jobs.begin();
while (job != jobs.end()) {
if (!job->stopped) {
job = jobs.erase(job)
} else {
++job;
}
}
But someone took a look at my code and said it's wrong which I doin't understand why?
If do not take into account the typo relative to the missing semicolon in this statement
job = jobs.erase(job)
^^^
and the second typo in this condition
if (!job->stopped) {
^^^^
which should be written like
if ( job->stopped) {
(that is you need to remove as you wrote all jobs with the set flag stopped) your code is correct but is redundant.
You could just write
jobs.remove_if( []( const auto &job ) { return job.stopped; } );
or
jobs.remove_if( []( const JobEntry &job ) { return job.stopped; } );
if this statement is called within a member function.
Edit: Here is a demonstrative program that uses your class declarations.
#include <iostream>
#include <string>
#include <list>
#include <ctime>
typedef int pid_t;
class JobsList {
public:
class JobEntry {
public:
pid_t pid, jid;
std::string cmd;
time_t in_time;
bool stopped;
JobEntry( int pid, int jid, const std::string &cmd, bool stopped )
:pid( pid ), jid( jid ), cmd( cmd ), stopped( stopped )
{}
// TODO: Add your data members
bool operator<( JobEntry const &tmp ) const {
return jid < tmp.jid;
}
bool operator==( JobEntry const &tmp ) const {
return jid == tmp.jid;
}
};
std::list<JobEntry> jobs;
};
int main()
{
JobsList jobs_list =
{
{
{ 1, 1, "first", false },
{ 2, 2, "second", true }
}
};
std::cout << jobs_list.jobs.size() << '\n';
jobs_list.jobs.remove_if( []( const auto &job ) { return job.stopped; } );
std::cout << jobs_list.jobs.size() << '\n';
}
I only introduced for simplicity this typedef
typedef int pid_t;
and changed a parameter declaration in the constructor
JobEntry( int pid, int jid, const std::string &cmd, bool stopped )
^^^^^^^

Storing vector of doubles into a text file [duplicate]

How do I do the following with std::cout?
double my_double = 42.0;
char str[12];
printf_s("%11.6lf", my_double); // Prints " 42.000000"
I am just about ready to give up and use sprintf_s.
More generally, where can I find a reference on std::ostream formatting that lists everything in one place, rather than spreading it all out in a long tutorial?
EDIT Dec 21, 2017 - See my answer below. It uses features that were not available when I asked this question in 2012.
std::cout << std::fixed << std::setw(11) << std::setprecision(6) << my_double;
You need to add
#include <iomanip>
You need stream manipulators
You may "fill" the empty places with whatever char you want. Like this:
std::cout << std::fixed << std::setw(11) << std::setprecision(6)
<< std::setfill('0') << my_double;
std::cout << boost::format("%11.6f") % my_double;
You have to #include <boost\format.hpp>
In C++20 you can to do
double my_double = 42.0;
char str[12];
std::format_to_n(str, sizeof(str), "{:11.6}", my_double);
or
std::string s = std::format("{:11.6}", my_double);
In pre-C++20 you can use the {fmt} library that provides an implementation of format_to_n.
Disclaimer: I'm the author of {fmt} and C++20 std::format.
In general, you want to avoid specifying things like 11 and 6 at the
point of output. That's physical markup, and you want logical markup;
e.g. pressure, or volume. That way, you define in a single place
how pressure or volume are formatted, and if that formatting changes,
you don't have to search through out the program to find where to change
the format (and accidentally change the format of something else). In
C++, you do this by defining a manipulator, which sets the various
formatting options, and preferrably restores them at the end of the full
expression. So you end up writing things like:
std::cout << pressure << my_double;
Although I definitly wouldn't use it in production code, I've found the
following FFmt formatter useful for quicky jobs:
class FFmt : public StateSavingManip
{
public:
explicit FFmt(
int width,
int prec = 6,
std::ios::fmtflags additionalFlags
= static_cast<std::ios::fmtflags>(),
char fill = ' ' );
protected:
virtual void setState( std::ios& targetStream ) const;
private:
int myWidth;
int myPrec;
std::ios::fmtflags myFlags;
char myFill;
};
FFmt::FFmt(
int width,
int prec,
std::ios::fmtflags additionalFlags,
char fill )
: myWidth( width )
, myPrec( prec )
, myFlags( additionalFlags )
, myFill( fill )
{
myFlags &= ~ std::ios::floatfield
myFlags |= std::ios::fixed
if ( isdigit( static_cast< unsigned char >( fill ) )
&& (myFlags & std::ios::adjustfield) == 0 ) {
myFlags |= std::ios::internal
}
}
void
FFmt::setState(
std::ios& targetStream ) const
{
targetStream.flags( myFlags )
targetStream.width( myWidth )
targetStream.precision( myPrec )
targetStream.fill( myFill )
}
This allows writing things like:
std::cout << FFmt( 11, 6 ) << my_double;
And for the record:
class StateSavingManip
{
public:
StateSavingManip(
StateSavingManip const& other );
virtual ~StateSavingManip();
void operator()( std::ios& stream ) const;
protected:
StateSavingManip();
private:
virtual void setState( std::ios& stream ) const = 0;
private:
StateSavingManip& operator=( StateSavingManip const& );
private:
mutable std::ios* myStream;
mutable std::ios::fmtflags
mySavedFlags;
mutable int mySavedPrec;
mutable char mySavedFill;
};
inline std::ostream&
operator<<(
std::ostream& out,
StateSavingManip const&
manip )
{
manip( out );
return out;
}
inline std::istream&
operator>>(
std::istream& in,
StateSavingManip const&
manip )
{
manip( in );
return in;
}
StateSavingManip.cc:
namespace {
// We maintain the value returned by ios::xalloc() + 1, and not
// the value itself. The actual value may be zero, and we need
// to be able to distinguish it from the 0 resulting from 0
// initialization. The function getXAlloc() returns this value
// -1, so we add one in the initialization.
int getXAlloc();
int ourXAlloc = getXAlloc() + 1;
int
getXAlloc()
{
if ( ourXAlloc == 0 ) {
ourXAlloc = std::ios::xalloc() + 1;
assert( ourXAlloc != 0 );
}
return ourXAlloc - 1;
}
}
StateSavingManip::StateSavingManip()
: myStream( NULL )
{
}
StateSavingManip::StateSavingManip(
StateSavingManip const&
other )
{
assert( other.myStream == NULL );
}
StateSavingManip::~StateSavingManip()
{
if ( myStream != NULL ) {
myStream->flags( mySavedFlags );
myStream->precision( mySavedPrec );
myStream->fill( mySavedFill );
myStream->pword( getXAlloc() ) = NULL;
}
}
void
StateSavingManip::operator()(
std::ios& stream ) const
{
void*& backptr = stream.pword( getXAlloc() );
if ( backptr == NULL ) {
backptr = const_cast< StateSavingManip* >( this );
myStream = &stream;
mySavedFlags = stream.flags();
mySavedPrec = stream.precision();
mySavedFill = stream.fill();
}
setState( stream );
}
#include <iostream>
#include <iomanip>
int main() {
double my_double = 42.0;
std::cout << std::fixed << std::setw(11)
<< std::setprecision(6) << my_double << std::endl;
return 0;
}
For future visitors who prefer actual printf-style format specs with std::ostream, here is yet another variation, based on Martin York's excellent post in another SO question: https://stackoverflow.com/a/535636:
#include <iostream>
#include <iomanip>
#include <stdio.h> //snprintf
class FMT
{
public:
explicit FMT(const char* fmt): m_fmt(fmt) {}
private:
class fmter //actual worker class
{
public:
explicit fmter(std::ostream& strm, const FMT& fmt): m_strm(strm), m_fmt(fmt.m_fmt) {}
//output next object (any type) to stream:
template<typename TYPE>
std::ostream& operator<<(const TYPE& value)
{
// return m_strm << "FMT(" << m_fmt << "," << value << ")";
char buf[40]; //enlarge as needed
snprintf(buf, sizeof(buf), m_fmt, value);
return m_strm << buf;
}
private:
std::ostream& m_strm;
const char* m_fmt;
};
const char* m_fmt; //save fmt string for inner class
//kludge: return derived stream to allow operator overloading:
friend FMT::fmter operator<<(std::ostream& strm, const FMT& fmt)
{
return FMT::fmter(strm, fmt);
}
};
usage example:
double my_double = 42.0;
cout << FMT("%11.6f") << my_double << "more stuff\n";
or even:
int val = 42;
cout << val << " in hex is " << FMT(" 0x%x") << val << "\n";
it's me, the OP, Jive Dadson - five years on. C++17 is becoming a reality.
The advent of variadic template parameters with perfect forwarding has made life so much simpler. The chained madness of ostream<< and boost::format% can be dispensed with. The function oprintf below fills the bill. Work in progress. Feel free to chime in on error-handling, etc...
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <string_view>
namespace dj {
template<class Out, class... Args>
Out& oprintf(Out &out, const std::string_view &fmt, Args&&... args) {
const int sz = 512;
char buffer[sz];
int cx = snprintf(buffer, sz, fmt.data(), std::forward<Args>(args)...);
if (cx >= 0 && cx < sz) {
return out.write(buffer, cx);
} else if (cx > 0) {
// Big output
std::string buff2;
buff2.resize(cx + 1);
snprintf(buff2.data(), cx, fmt.data(), std::forward<Args>(args)...);
return out.write(buff2.data(), cx);
} else {
// Throw?
return out;
}
}
}
int main() {
const double my_double = 42.0;
dj::oprintf(std::cout, "%s %11.6lf\n", "My double ", my_double);
return 0;
}
Some great answers already; kudos to those!
This is based on some of them. I have added type assertions for POD types, since they are the only safe types usable with printf().
#include <iostream>
#include <stdio.h>
#include <type_traits>
namespace fmt {
namespace detail {
template<typename T>
struct printf_impl
{
const char* fmt;
const T v;
printf_impl(const char* fmt, const T& v) : fmt(fmt), v(v) {}
};
template<typename T>
inline typename std::enable_if<std::is_pod<T>::value, std::ostream& >::type
operator<<(std::ostream& os, const printf_impl<T>& p)
{
char buf[40];
::snprintf(buf, sizeof(buf), p.fmt, p.v, 40);
return os << buf;
}
} // namespace detail
template<typename T>
inline typename std::enable_if<std::is_pod<T>::value, detail::printf_impl<T> >::type
printf(const char* fmt, const T& v)
{
return detail::printf_impl<T>(fmt, v);
}
} // namespace fmt
Example usage it as below.
std::cout << fmt::printf("%11.6f", my_double);
Give it a try on Coliru.

load a file of 1's and 0's into a char** line by line

I have a file, at the end of each line there is possibly a newline:
111\n
100\n
101
In C++ you can load the lines of a file into an array of byte strings like this:
auto lines_from( istream& is )
-> vector<string>
{
string line;
vector<string> result;
while( getline( is, line ) )
{
result.push_back( line );
}
return result;
}
auto main() -> int
{
vector<string> const lines = lines_from( cin );
// Use it.
}
Here string is std::string from the <string> header, getline is std::getline from the same header, and vector is std::vector from the <vector> header. I chose to use a descriptive name for the function, lines_from. However, it's commonly named readall.
Where you absolutely need a char**, presumably with an assumption of some given buffer size for each string, then you can use a vector of pointers, pointing to buffers that e.g. are managed by a class like this:
class C_strings
{
private:
vector<string> buffers_;
vector<char*> pointers_;
int bufsize_;
C_strings( C_strings const& ) = delete;
auto operator=( C_strings const& ) -> C_strings& = delete;
public:
auto pointer() -> char** { return pointers_.data(); }
auto bufsize() const -> int { return bufsize_; }
C_strings( vector<string> const& strings, int const bufsize )
: buffers_( strings )
, bufsize_( bufsize )
{
pointers_.reserve( buffers_.size() + 1 );
for( string& s : buffers_ )
{
s.reserve( bufsize );
if( s.empty() or s.back() != '\0' ) { s += '\0'; }
pointers_.push_back( &s[0] );
}
pointers_.push_back( nullptr );
}
C_strings( C_strings&& other )
: buffers_( move( other.buffers_ ) )
, pointers_( move( other.pointers_ ) )
{}
};
Then let's say you want to call a double-star function like this:
void doublestarfunc( char** const lines )
{
using std::cout;
for( char** pps = lines; *pps != nullptr; ++pps )
{
if( strlen( *pps ) < 40 ) { strcat( *pps, " < Oh la la!" ); }
cout << *pps << '\n';
}
cout << '\n';
}
It can be done very simply:
using namespace std; // cin, cout
int const columns = 80;
int const cstring_bufsize = columns + 1;
auto c_strings = C_strings( lines_from( cin ), cstring_bufsize );
doublestarfunc( c_strings.pointer() );
But is it a good idea? No, except when you have to relate to an existing C style API. For C++ code, better restructure it to use C++ std::string throughout.

Floating point format for std::ostream

How do I do the following with std::cout?
double my_double = 42.0;
char str[12];
printf_s("%11.6lf", my_double); // Prints " 42.000000"
I am just about ready to give up and use sprintf_s.
More generally, where can I find a reference on std::ostream formatting that lists everything in one place, rather than spreading it all out in a long tutorial?
EDIT Dec 21, 2017 - See my answer below. It uses features that were not available when I asked this question in 2012.
std::cout << std::fixed << std::setw(11) << std::setprecision(6) << my_double;
You need to add
#include <iomanip>
You need stream manipulators
You may "fill" the empty places with whatever char you want. Like this:
std::cout << std::fixed << std::setw(11) << std::setprecision(6)
<< std::setfill('0') << my_double;
std::cout << boost::format("%11.6f") % my_double;
You have to #include <boost\format.hpp>
In C++20 you can to do
double my_double = 42.0;
char str[12];
std::format_to_n(str, sizeof(str), "{:11.6}", my_double);
or
std::string s = std::format("{:11.6}", my_double);
In pre-C++20 you can use the {fmt} library that provides an implementation of format_to_n.
Disclaimer: I'm the author of {fmt} and C++20 std::format.
In general, you want to avoid specifying things like 11 and 6 at the
point of output. That's physical markup, and you want logical markup;
e.g. pressure, or volume. That way, you define in a single place
how pressure or volume are formatted, and if that formatting changes,
you don't have to search through out the program to find where to change
the format (and accidentally change the format of something else). In
C++, you do this by defining a manipulator, which sets the various
formatting options, and preferrably restores them at the end of the full
expression. So you end up writing things like:
std::cout << pressure << my_double;
Although I definitly wouldn't use it in production code, I've found the
following FFmt formatter useful for quicky jobs:
class FFmt : public StateSavingManip
{
public:
explicit FFmt(
int width,
int prec = 6,
std::ios::fmtflags additionalFlags
= static_cast<std::ios::fmtflags>(),
char fill = ' ' );
protected:
virtual void setState( std::ios& targetStream ) const;
private:
int myWidth;
int myPrec;
std::ios::fmtflags myFlags;
char myFill;
};
FFmt::FFmt(
int width,
int prec,
std::ios::fmtflags additionalFlags,
char fill )
: myWidth( width )
, myPrec( prec )
, myFlags( additionalFlags )
, myFill( fill )
{
myFlags &= ~ std::ios::floatfield
myFlags |= std::ios::fixed
if ( isdigit( static_cast< unsigned char >( fill ) )
&& (myFlags & std::ios::adjustfield) == 0 ) {
myFlags |= std::ios::internal
}
}
void
FFmt::setState(
std::ios& targetStream ) const
{
targetStream.flags( myFlags )
targetStream.width( myWidth )
targetStream.precision( myPrec )
targetStream.fill( myFill )
}
This allows writing things like:
std::cout << FFmt( 11, 6 ) << my_double;
And for the record:
class StateSavingManip
{
public:
StateSavingManip(
StateSavingManip const& other );
virtual ~StateSavingManip();
void operator()( std::ios& stream ) const;
protected:
StateSavingManip();
private:
virtual void setState( std::ios& stream ) const = 0;
private:
StateSavingManip& operator=( StateSavingManip const& );
private:
mutable std::ios* myStream;
mutable std::ios::fmtflags
mySavedFlags;
mutable int mySavedPrec;
mutable char mySavedFill;
};
inline std::ostream&
operator<<(
std::ostream& out,
StateSavingManip const&
manip )
{
manip( out );
return out;
}
inline std::istream&
operator>>(
std::istream& in,
StateSavingManip const&
manip )
{
manip( in );
return in;
}
StateSavingManip.cc:
namespace {
// We maintain the value returned by ios::xalloc() + 1, and not
// the value itself. The actual value may be zero, and we need
// to be able to distinguish it from the 0 resulting from 0
// initialization. The function getXAlloc() returns this value
// -1, so we add one in the initialization.
int getXAlloc();
int ourXAlloc = getXAlloc() + 1;
int
getXAlloc()
{
if ( ourXAlloc == 0 ) {
ourXAlloc = std::ios::xalloc() + 1;
assert( ourXAlloc != 0 );
}
return ourXAlloc - 1;
}
}
StateSavingManip::StateSavingManip()
: myStream( NULL )
{
}
StateSavingManip::StateSavingManip(
StateSavingManip const&
other )
{
assert( other.myStream == NULL );
}
StateSavingManip::~StateSavingManip()
{
if ( myStream != NULL ) {
myStream->flags( mySavedFlags );
myStream->precision( mySavedPrec );
myStream->fill( mySavedFill );
myStream->pword( getXAlloc() ) = NULL;
}
}
void
StateSavingManip::operator()(
std::ios& stream ) const
{
void*& backptr = stream.pword( getXAlloc() );
if ( backptr == NULL ) {
backptr = const_cast< StateSavingManip* >( this );
myStream = &stream;
mySavedFlags = stream.flags();
mySavedPrec = stream.precision();
mySavedFill = stream.fill();
}
setState( stream );
}
#include <iostream>
#include <iomanip>
int main() {
double my_double = 42.0;
std::cout << std::fixed << std::setw(11)
<< std::setprecision(6) << my_double << std::endl;
return 0;
}
For future visitors who prefer actual printf-style format specs with std::ostream, here is yet another variation, based on Martin York's excellent post in another SO question: https://stackoverflow.com/a/535636:
#include <iostream>
#include <iomanip>
#include <stdio.h> //snprintf
class FMT
{
public:
explicit FMT(const char* fmt): m_fmt(fmt) {}
private:
class fmter //actual worker class
{
public:
explicit fmter(std::ostream& strm, const FMT& fmt): m_strm(strm), m_fmt(fmt.m_fmt) {}
//output next object (any type) to stream:
template<typename TYPE>
std::ostream& operator<<(const TYPE& value)
{
// return m_strm << "FMT(" << m_fmt << "," << value << ")";
char buf[40]; //enlarge as needed
snprintf(buf, sizeof(buf), m_fmt, value);
return m_strm << buf;
}
private:
std::ostream& m_strm;
const char* m_fmt;
};
const char* m_fmt; //save fmt string for inner class
//kludge: return derived stream to allow operator overloading:
friend FMT::fmter operator<<(std::ostream& strm, const FMT& fmt)
{
return FMT::fmter(strm, fmt);
}
};
usage example:
double my_double = 42.0;
cout << FMT("%11.6f") << my_double << "more stuff\n";
or even:
int val = 42;
cout << val << " in hex is " << FMT(" 0x%x") << val << "\n";
it's me, the OP, Jive Dadson - five years on. C++17 is becoming a reality.
The advent of variadic template parameters with perfect forwarding has made life so much simpler. The chained madness of ostream<< and boost::format% can be dispensed with. The function oprintf below fills the bill. Work in progress. Feel free to chime in on error-handling, etc...
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <string_view>
namespace dj {
template<class Out, class... Args>
Out& oprintf(Out &out, const std::string_view &fmt, Args&&... args) {
const int sz = 512;
char buffer[sz];
int cx = snprintf(buffer, sz, fmt.data(), std::forward<Args>(args)...);
if (cx >= 0 && cx < sz) {
return out.write(buffer, cx);
} else if (cx > 0) {
// Big output
std::string buff2;
buff2.resize(cx + 1);
snprintf(buff2.data(), cx, fmt.data(), std::forward<Args>(args)...);
return out.write(buff2.data(), cx);
} else {
// Throw?
return out;
}
}
}
int main() {
const double my_double = 42.0;
dj::oprintf(std::cout, "%s %11.6lf\n", "My double ", my_double);
return 0;
}
Some great answers already; kudos to those!
This is based on some of them. I have added type assertions for POD types, since they are the only safe types usable with printf().
#include <iostream>
#include <stdio.h>
#include <type_traits>
namespace fmt {
namespace detail {
template<typename T>
struct printf_impl
{
const char* fmt;
const T v;
printf_impl(const char* fmt, const T& v) : fmt(fmt), v(v) {}
};
template<typename T>
inline typename std::enable_if<std::is_pod<T>::value, std::ostream& >::type
operator<<(std::ostream& os, const printf_impl<T>& p)
{
char buf[40];
::snprintf(buf, sizeof(buf), p.fmt, p.v, 40);
return os << buf;
}
} // namespace detail
template<typename T>
inline typename std::enable_if<std::is_pod<T>::value, detail::printf_impl<T> >::type
printf(const char* fmt, const T& v)
{
return detail::printf_impl<T>(fmt, v);
}
} // namespace fmt
Example usage it as below.
std::cout << fmt::printf("%11.6f", my_double);
Give it a try on Coliru.

C++ comparing bunch of values with a given one

I need to compare one given value with a retrieved values. I do this several times in the code. I am not satisfied with how it looks and I am seeking for a some sort of an util function. Anyone wrote one?
Number of values I am comparing with is known at the compile time.
Update: I'd like to get rid of containers as I know exact amount of values ( often not more then 3 ) I want to compare with. And it is not so convenient to put items to the container every time.
I don't love if neither because it is not obvious as "find".
#include <algorithm>
#include <string>
#include <vector>
std::string getValue1()
{
return "test";
}
std::string getValue2()
{
return "the";
}
std::string getValue3()
{
return "world";
}
int main()
{
const std::string value = "the";
// simple if
if ( value == getValue1() ||
value == getValue2() ||
value == getValue3() )
return 1;
// using collections like vector, set
std::vector<std::string> values;
values.push_back( getValue1() );
values.push_back( getValue2() );
values.push_back( getValue3() );
if ( values.end() != std::find( values.begin(), values.end(), value ) )
return 1;
// third option I'd use instead
//
return 0;
}
If the values you're looking for are Comparable with operator< (like ints, float and std::strings), then it's faster to use an std::set to put the values there and then check set.find(value) == set.end(). This is because the set will store the values with a certain order that allows for faster lookups. Using an hash table will be even faster. However, for less than 50 values or so you might not notice any difference :) So my rule of thumb would be:
Less then 5 items: if with multiple ||
5 or more: put in a set or hash table
you can write a set of template functions which will help you through with this, for example:
template <typename T>
bool InSet(const T & item, const T & i1, const T & i2) {
return item==i1 || item==i2;
}
template <typename T>
bool InSet(const T & item, const T & i1, const T & i2, const T & i3) {
return item==i1 || item==i2 || item==i3;
}
Note that you can make InSet to work like it took a variable number of arguments by creating multiple templates with different number of arguments.
And then:
int i;
if (InSet(i, 3, 4, 5)) { ... }
string s;
if (InSet(s, "foobar", "zap", "garblex")) { ... }
etc.
For your request to do
if (InSet(value)(GetValue1(), GetValue2(), GetValue3()))
{
// Do something here...
}
Try this:
template <typename T>
class InSetHelper
{
const T &Value;
void operator=(const InSetHelper &);
public:
InSetHelper(const T &value) : Value(value) {}
template<class Other, class Another>
bool operator()(const Other &value1, const Another &value2) const
{
return Value == value1 || Value == value2;
}
template<class Other, class Another, class AThird>
bool operator()(const Other &value1, const Another &value2, const AThird &value3) const
{
return Value == value1 || Value == value2 || Value == value3;
}
};
template <typename T>
InSetHelper<T> InSet(const T &value) { return InSetHelper<T>(value); }
This syntax might be more clear though:
if (MakeSet(GetValue1(), GetValue2(), GetValue3()).Contains(value))
{
// Do something here...
}
template <typename T, typename U, typename V>
class Set3
{
const T& V1;
const U& V2;
const V& V3;
void operator=(const Set3 &);
public:
Set3(const T &v1, const U &v2, const V &v3) : V1(v1), V2(v2), V3(v3) {}
template <typename W>
bool Contains(const W &v) const
{
return V1 == v || V2 == v || V3 == v;
}
};
template <typename T, typename U>
class Set2
{
// as above
};
template <typename T, typename U, typename V>
Set3<T, U, V> MakeSet(const T &v1, const U &v2, const V &v3)
{
return Set3<T, U, V>(v1, v2, v3);
}
template <typename T, typename U>
Set3<T, U> MakeSet(const T &v1, const U &v23)
{
return Set3<T, U, V>(v1, v2);
}
If those values are really part of a tree or a linked list, then you have your set/container already, and your best bet is to just use some recursion:
parent.ThisOrDescendantHasValue(value);
You'd just add this to whatever class parent and child belong to:
class Node
{
public:
Value GetValue();
Node *GetChild();
bool ThisOrDescendantHasValue(const Value &value)
{
return GetValue() == value
|| (GetChild() && GetChild->ThisOrDescendantHasValue(value));
}
};
You don't need a std::set or a std::vector. Just use std::set_intersection()...
Code is best...
#include <set>
#include <iostream>
#include <iterator>
using namespace std;
#define COUNT(TYPE,ARRAY) ( sizeof(ARRAY) / sizeof(TYPE) )
inline bool CaseInsensitiveCompare (const char * a, const char * b)
{ return strcasecmp( a, b ) < 0; }
int main()
{
const char * setA[] = { "the", "world", "is", "flat" };
const char * setB[] = { "the", "empty", "set", "is", "boring" };
stable_sort( setA, setA + COUNT( const char *, setA ),
CaseInsensitiveCompare );
stable_sort( setB, setB + COUNT( const char *, setB ),
CaseInsensitiveCompare );
cout << "Intersection of sets: ";
set_intersection( setA, setA + COUNT( const char *, setA ),
setB, setB + COUNT( const char *, setB ),
ostream_iterator<const char *>(cout, " "),
CaseInsensitiveCompare );
cout << endl << endl;
}
Or perhaps, given your 1-N lookup problem:
(Note: Use binary_search() AFTER sorting!)
if ( binary_search( setA, setA + COUNT( const char *, setA ),
"is", CaseInsensitiveCompare ) )
...
if ( binary_search( setA, setA + COUNT( const char *, setA ),
"set", CaseInsensitiveCompare ) )
...
Which changes more, the 'value' or the values returned by 'getValueX()'? You can insert everything into a hash_map/map and then do a search that way, as you've suggested with the containers.
std::find_first_of.
Of course, if you only care about finding a single value, you can create your own wrapper around std::find.
I would recommend your method 2, using a std::vector or other container and looking for membership. Since the order of elements that you're checking against is probably not relevant, you may want to use a std::set or std::map. If you have very many items in your set of values, then using a set or a map will be a faster, while if you have only a few a vector may be faster.
The advantage of any of these approaches is that you can then store the set/map somewhere common, and avoid having to build the set of matching responses every time.
i like the collections approach, maybe use a hash_set instead of a vector. store the values in a property file and have a method to populat the hash_set from the file, and another one to return a boolean if the value is in the hash_set. then you can get down to one 2 lines in the main code.
It depends on the source of the retrieved values, if you're reading in from a file or stream then you'd do something different but if your source is a series of functions then the following is a different way to do it, not perfect but may suit your needs:
const int count = 3;
std::string value = "world";
boost::function<std::string(void)> funcArray[count];
funcArray[0] = &getValue1;
funcArray[1] = &getValue2;
funcArray[2] = &getValue3;
for( int i = 0; i < count; ++i )
{
if( funcArray[i]() == value )
return 1;
}
If you know which functions are the source (as well as the count of objects) I expect you could assemble the function pointer array using the preprocessor.
How about using a boost::array (or std::tr1::array) and creating a simple function like this:
template <typename ValueType, size_t arraySize>
bool contains(const boost::array<ValueType, arraySize>& arr, const ValueType& val)
{
return std::find(arr.begin(), arr.end(), val)!=arr.end();
}
You could then reuse that pretty easily:
#include <string>
#include <iostream>
#include <boost\array.hpp>
template <typename ValueType, size_t arraySize>
bool contains(const boost::array<ValueType, arraySize>& arr, const ValueType& val)
{
return std::find(arr.begin(), arr.end(), val)!=arr.end();
}
int _tmain(int argc, _TCHAR* argv[])
{
boost::array<std::string, 3> arr = {"HI", "there", "world"};
std::cout << std::boolalpha
<< "arr contains HI: " << contains(arr, std::string("HI")) << std::endl
<< "arr contains blag: " << contains(arr, std::string("blag") ) << std::endl
<< "arr contains there: " << contains(arr, std::string("there") ) << std::endl;
return 0;
}
Edit: So boost is out. It's pretty easy to adapt this to a regular array:
template <typename ValueType, size_t arraySize>
bool contains(ValueType (&arr)[arraySize], const ValueType& val)
{
return std::find(&arr[0], &arr[arraySize], val)!=&arr[arraySize];
}
int _tmain(int argc, _TCHAR* argv[])
{
std::string arr[3] = {"HI", "there", "world"};
std::cout << std::boolalpha << "arr contains HI: " << contains(arr, std::string("HI")) << std::endl
<< "arr contains blag: " << contains(arr, std::string("blag") ) << std::endl
<< "arr contains there: " << contains(arr, std::string("there") ) << std::endl;
return 0;
}