Meysam
Meysam

Reputation: 18137

Is it possible to use templates to identify two different types?

I've got the following code. I have to define the operator() for all types available in MyVariant (bool, int, string, const char*). However, since StartsWith is only applicable to type string, all other functors should return false.

#include "boost/variant/variant.hpp"
#include "boost/variant/apply_visitor.hpp"

using namespace std;
using namespace boost;

typedef variant<bool, int, string, const char*> MyVariant;

class StartsWith
    : public boost::static_visitor<bool>
{
public:
    string mPrefix;
    bool operator()(string &other) const
    {
        return other.compare(0, mPrefix.length(), mPrefix);
    }
    bool operator()(int &other) const
    {
        return false;
    }
    bool operator()(bool &other) const
    {
        return false;
    }
    bool operator()(const char* other) const
    {
        return false;
    }
    StartsWith(string const& prefix):mPrefix(prefix){}
};

int main(int argc, char **argv) 
{
    MyVariant s1 = "hello world!";
    if(apply_visitor(StartsWith("hel"), s1))
    {
        cout << "starts with" << endl;
    }
    return 0;
}

The above code works fine. But in order to make it more concise, I thought it might be possible to use templates to have one functor for string, and one for other types. I tried the following, but the result is that the second functor is always the one invoked.

template<typename T>
class StartsWith
    : public boost::static_visitor<bool>
{
public:
    T mPrefix;
    bool operator()(T &other) const
    {
        return other.compare(0, mPrefix.length(), mPrefix);
    }
    template<typename U>
    bool operator()(U &other)const
    {
        return false;
    }
    StartsWith(T const& prefix):mPrefix(prefix){}
};

The following code did not work either:

class StartsWith
    : public boost::static_visitor<bool>
{
public:
    string mPrefix;
    bool operator()(string &other) const
    {
        return other.compare(0, mPrefix.length(), mPrefix);
    }
    template<typename U>
    bool operator()(U &other)const
    {
        return false;
    }
    StartsWith(string const& prefix):mPrefix(prefix){}
};

Is there anyway I can avoid multiple "return false" statements for types other than string?

Upvotes: 0

Views: 188

Answers (3)

Meysam
Meysam

Reputation: 18137

The problem was that I was using const char* in my variant. Changing the following line:

MyVariant s1 = "hello world!";

to

MyVariant s1 = string("hello world!");

solved the problem and got the template version working.

Upvotes: 1

Olaf Dietsche
Olaf Dietsche

Reputation: 74028

This one works for me:

class StartsWith
    : public boost::static_visitor<bool>
{
public:
    string mPrefix;
    bool operator()(const string &other) const
    {
        return other.compare(0, mPrefix.length(), mPrefix);
    }
    template<typename U>
    bool operator()(U other)const
    {
        return false;
    }
    StartsWith(string const& prefix):mPrefix(prefix){}
};

Off topic: std::string::compare() returns int.

Upvotes: 1

BigBoss
BigBoss

Reputation: 6914

bool operator()(std::string const& other ) const {...}
template< class T >
typename boost::disable_if<boost::is_same<T, std::string>, bool >::type
operator()( T const& ) const {return false;}

Upvotes: 2

Related Questions