Błąd expected primary-expression before ‘>’ token

0

Witam ponownie, mam taki kod:


#include  <iostream>
#include <type_traits> 

struct widget
{
    int id;
    std::string name;

    std::ostream& write(std::ostream& os) const
    {
        os << id << ',' << name << '\n';
        return os;
    }
};

struct gadget 
{
    int id;
    std::string name;

    friend std::ostream& operator <<(std::ostream& os, gadget const& o);
};

std::ostream& operator <<(std::ostream& os, gadget const& o)
{
    os << o.id << ',' << o.name << '\n';
    return os;
};

template<typename T>
struct uses_write
{
    static constexpr bool value = false;
};

template<>
struct uses_write<widget>
{
    static constexpr bool value = true;
};

template<typename T>
inline constexpr bool uses_write_v = uses_write<T>::value;

template<bool>
struct serializer
{
    template<typename T>
    static void serialize(std::ostream& os, T const& value)
    {
        os << value;
    }
};

template<>
struct serializer<true>
{
    template<typename T>
    static void serialize(std::ostream& os, T const& value)
    {
        value.write(os);
    }
};

template<typename T>
void serialize(std::ostream& os, T const& val)
{
    serializer<uses_write_v<T>>::serialize<T>(os, val);
}

int main() {
   widget w{1, "one"};
   serialize(std::cout, w);

   gadget g{2, "two"};
   serialize(std::cout, g);
}

Dostaje error: a.cpp:69:45: error: expected primary-expression before ‘>’ token serializer<uses_write_v<T>>::serialize<T>(os, val);

Ale jak zmienie linie 69 na serializer<uses_write_v<T>>::serialize(os, val); to program się kompiluje i działa poprawnie. Dlaczego tak się dzieje?

2
template<typename T>
void serialize(std::ostream& os, T const& val)
{
    serializer<uses_write_v<T>>::template serialize<T>(os, val);
}

https://godbolt.org/z/hzd4e1fsY

Jakiego kompilatora użyłeś? gcc i clang dość jasno mówią w czym problem (a format błedu wskazuje, że to jeden z nich).

<source>: In function 'void serialize(std::ostream&, const T&)':
<source>:68:34: error: expected 'template' keyword before dependent template name [-Werror=missing-template-keyword]
   68 |     serializer<uses_write_v<T>>::serialize<T>(os, val);
      |                                  ^~~~~~~~~
      |                                  template

https://godbolt.org/z/cGrer7311


a dobra teraz widzę, że ja używam flag -Wall -Wextra -Werror -pedantic, a ty po prostu zignorowałeś ostrzeżenia.
Radziłbym, używać tych flag kompilatora.

0

Dzięki za pomoc. A Wiesz dlaczego trzeba jawnie wpisać template przed serialize<T>(os, val); ?

2

https://en.cppreference.com/w/cpp/language/dependent_name#The_template_disambiguator_for_dependent_names

Słowo kluczowe template jest potrzebne, aby wskazać, że następująca nazwa odnosi się do zależnej nazwy szablonu, a nie członka bieżącej instancji.
Kompilator C++ nie może wydedukować, czy zależna nazwa jest typem czy wartością, więc domyślnie przyjmuje, że jest to wartość.

Problem występuje jak definiujesz szablon, który odnosi się do innego szablonu. Jak się kompiluje ten szablon i parametry szablonu nie są jeszcze znany, to w ten sposób tłumaczsz kompilatorowi, że symbol zależny jest również szablonem.

1 użytkowników online, w tym zalogowanych: 0, gości: 1