Can't figure out syntax error with templates/member function pointers

Discussion in 'C++' started by Aaron Walker, Oct 1, 2005.

  1. Aaron Walker

    Aaron Walker Guest

    Greetings,

    I'm attempting to write my first *real* template function that also deals with
    a map of strings to member function pointers that is making the syntax a little
    tricky to get right.

    The function in question:

    36: template <typename Container,
    37: typename OutputIterator,
    38: typename UnaryOp>
    39: void
    40: transform_fields_into_matches(
    41: typename Container::const_iterator first,
    42: typename Container::const_iterator last,
    43: OutputIterator result,
    44: const fields_type& fields,
    45: const std::map<std::string,
    46: const std::string& (Container::value_type::*)(void) const > & fm,
    47: UnaryOp op)
    48: {
    49: typedef const std::string& (Container::value_type::*mfp)(void) const;
    50:
    51: util::Regex criteria;
    52: const int cflags(options::eregex() ?
    53: util::Regex::extended|util::Regex::icase : util::Regex::icase);
    54:
    55: for (; first != last ; ++first)
    56: {
    57: fields_type::const_iterator f;
    58: for (f = fields.begin() ; f != fields.end() ; ++f)
    59: {
    60: /* check if field is valid */
    61: std::map<std::string, mfp>::const_iterator i = fm.find(f->first);
    62: if (i == fm.end())
    63: throw InvalidField(f->first);
    64:
    65: /* it's valid, so compile regex */
    66: criteria.assign(f->second, cflags);
    67:
    68: /* compare criteria against the return value of the
    69: * Container::value_type member function mapped to
    70: * this field. */
    71: const typename Container::value_type& v(*first);
    72: if (criteria != (v.*(i->second))())
    73: break;
    74:
    75: /* we're on the last field, meaning all fields that came before
    76: * it also matched, so save it finally. */
    77: if ((f+1) == fields.end())
    78: *result++ = op(*first);
    79: }
    80: }
    81: }

    For some reason I can't figure out, the compile keeps bailing on line 61 with:
    "error: expected ';' before i".

    I'm thinking maybe it has something to do with the lack of 'typename' when
    using Container::value_type in the function pointer, but adding that seems to
    cause another problem (maybe I'm not putting it in the right place?)

    using:
    typedef const std::string& (typename Container::value_type::*mfp)(void) const;

    causes:
    error: expected unqualified-id before ‘typename’
    error: expected `)' before ‘typename’
    error: expected initializer before ‘typename’

    Any pointers in the right direction?

    Much appreciated,
    Aaron
     
    Aaron Walker, Oct 1, 2005
    #1
    1. Advertisements

  2. well I'm not sure of your actual question because that is wildly complex
    syntax you have. But I can see that you are heading in the wrong direction.

    Look at this simple code

    #include <vector>

    template <typename Container>
    void f(typename Container::iterator i)
    {
    typename Container::value_type v;
    }

    int main()
    {
    std::vector<int> i;
    f(i.begin());
    }

    It fails to compile. The reason is that the compiler cannot work out
    what Container is. The rules of C++ prevent the compiler from deducing
    the template argument when the function argument type is of the form
    typename T::m.

    If you ever got your code to compile you would face this issue and there
    isn't a solution (other than specifying the template arguments explcitily).

    To pass iterators to a template function you should do the following and
    use iterator_traits if you want the value type.

    #include <vector>

    template <typename I>
    void f(I i)
    {
    std::iterator_traits<I>::value_type v;
    }

    int main()
    {
    std::vector<int> i;
    f(i.begin());
    }

    john
     
    John Harrison, Oct 1, 2005
    #2
    1. Advertisements

  3. Please don't post line numbers. Just add a comment to the line you
    want to mark.
    Add 'typename' at the beginning:

    Probably.

    V
     
    Victor Bazarov, Oct 1, 2005
    #3
  4. Aaron Walker

    Aaron Walker Guest

    <snip>

    My question was why would this:

    49: typedef const std::string& (Container::value_type::*mfp)(void) const;
    ....
    61: std::map<std::string, mfp>::const_iterator i = fm.find(f->first);

    produce this compile failure:

    61: "error: expected ';' before i".

    <snip>

    I was wondering if it'd be able to deduce the container type, but hadn't gotten
    that far due to the syntax error. I didn't realize I could get the value_type
    from iterator_traits.

    Thanks for helping with what would probably have been my next problem :)

    Aaron
     
    Aaron Walker, Oct 1, 2005
    #4
  5. Aaron Walker

    Aaron Walker Guest

    Ah, ok apologies. I figured it'd make it easier on whoever was trying to help.
    Will keep in mind next time.
    Yep, that does it.

    Thanks,
    Aaron
     
    Aaron Walker, Oct 1, 2005
    #5
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.