1

I would like to have two template structs for converting any Variant type to std::strings;

While the first one compiles, the second one will not compile, at the vector<Variant>::iterator statement. The compiler says:

error: expected ';' after expression

vector<Variant>::iterator i = data.begin();

Any idea what am I doing wrong? Is there a better way for what I am trying to do here?

template <typename Variant>
struct to_string
{
private:
    Variant data;

public:
    to_string(Variant &d) : data(d) {}
    operator std::string() const
    {
        try
        {
            return boost::lexical_cast<std::string>(data);
        }
        catch (const boost::bad_lexical_cast &)
        {
            return std::string();
        }
    }

};

template <typename Variant>
struct to_string_vector
{
private:
    vector<Variant> data;
public:
    to_string_vector(vector<Variant> &d) : data(d) {}
    operator vector<std::string> () const
    {
        vector<string> ret;
        vector<Variant>::iterator i = data.begin();
        to_string t_s<Variant> s = to_string<Variant>(*i);
        ret.push_back((string)s);
        return ret;
    }
};
johnsyweb
  • 136,902
  • 23
  • 188
  • 247
user3211860
  • 23
  • 1
  • 3

3 Answers3

3

You need

typename vector<Variant>::iterator

the compiler gets confused when accessing subclassess or typedefs defined within the scope of a templated type and needs help identifying them as types.

Edit: (my full program, fixing some const.... commented out the boost part since I don't have boost accessible right now... and added code to instantiate the templates).

#include <iostream>
#include <string>
#include <vector>

using namespace std;

template <typename Variant>
struct to_string
{
private:
    Variant data;

public:
    to_string(const Variant &d) : data(d) {}
    operator std::string() const
    {
        //try
        //{
            //return boost::lexical_cast<std::string>(data);
        //}
        //catch (const boost::bad_lexical_cast &)
        //{
            return std::string();
        //}
    }

};

template <typename Variant>
struct to_string_vector
{
private:
    vector<Variant> data;
public:
    to_string_vector(const vector<Variant> &d) : data(d) {}
    operator vector<std::string> () const
    {
        vector<string> ret;
        typename vector<Variant>::const_iterator i = data.begin();
        to_string<Variant> s = to_string<Variant>(*i);
        ret.push_back((string)s);
        return ret;
    }
};

int main(int argc,char  **argv) {

 to_string<int> a(10);

 string sa=(string)a;
 vector<int> v;
 to_string_vector<int> b(v);
 vector<string> sb=(vector<string>)b;
}
jsantander
  • 4,972
  • 16
  • 27
  • 1
    Expanding on this; without `typename` the compiler assumes that `vector::iterator` is a variable name, hence the error message. After all you could invoke this template with a specialization of `vector` where you had a variable called `iterator`. These rules are designed so the compiler can do some checking and maybe even some partial compilation of a template without yet knowing which types it will be instantiated with. – M.M Mar 28 '14 at 05:39
  • Many thanks for your reply and fix! :-) If you have a idea about a more elegant or generic way to do the same thing, please post it:) – user3211860 Mar 28 '14 at 07:09
1

Change vector::iterator i = data.begin(); to

typename vector::iterator i = data.begin();

Please take a look at vector<T>::iterator - invalid?

Community
  • 1
  • 1
nspforever
  • 66
  • 4
0

While the first one compiles

I am not so sure about that. Code that templates generates are complied as long as your other code uses it.

In both structs you are accessing non-const variable members from a const declared function. Either you remove the const keyword form your functions, or you will need to add the mutable keyword to your variables.

rodix
  • 425
  • 4
  • 13
  • 1
    Just looking at "the first one" in isolation - while the constructor has no apparent reason to take or store the `Variant` by non-`const` reference, it's not illegal to do so if the calling context provides an lvalue. Regarding *"you are accessing non-const variable members from a const declared function"* - that's true in `operator std::string() const`, but non-mutating access ala `lexical_cast<>` is allowed in a `const` function. – Tony Delroy Mar 28 '14 at 06:36