-2

I'm trying to write a generic function to serialize to string a std::vector<cv::Point_<T>> and I want this to work for both cv::Point2i and cv::Point2f (both are typedefs of cv::Point_<T> with a specific T).

The function looks like this:

template<typename T>
int SVIniFile::write(const std::string& section,
                     const std::string& key, 
                     std::vector<cv::Point_<T>>& points)
{
    std::ostringstream os;
    if (points.empty())
    {
        return SUCCESS;
    }
    for (size_t j = 0; j < points.size(); j++)
    {
        os << points[j].x << " " << points[j].y;
        if (j < points.size() - 1)
        {
            os << " ";
        }
    }

    write(section, key, os.str()); // do the writing of os.str() in the right `section` at `key`

    return SUCCESS; // function that writes a string into an ini file
}

Trying to compile this throws an "Unrecognizable template declaration/definition" error. Investigating on the error (full compiler output is below), I found this question, which however doesn't seem related to my case, and this question, the answer of which I don't understand.

I'm very new to template programming and I suspect the error is caused by the fact that I'm using as template parameter the type that is itself a template parameter of one of the parameters. Could anyone point me in the right direction and possibly expand a bit on why the compiler can't build this?


This is what the compiler produces as error output in every file where my header is included:

1>svinifile.h(640): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int 1>svinifile.h(640): error C2988: unrecognizable template declaration/definition 1>svinifile.h(640): error C2143: syntax error: missing ',' before '&'

line 640 is the one right after the template<typename T> in the function definition I show above.


Just to be explicit, cv::Point_<T> i OpenCV's 2D point type defined in types.hpp as:

namespace cv
{    
// ...
template<typename _Tp> class Point_
{
public:
    typedef _Tp value_type;

    //! default constructor
    Point_();
    Point_(_Tp _x, _Tp _y);
    Point_(const Point_& pt);
    Point_(Point_&& pt) CV_NOEXCEPT;
    Point_(const Size_<_Tp>& sz);
    Point_(const Vec<_Tp, 2>& v);

    Point_& operator = (const Point_& pt);
    Point_& operator = (Point_&& pt) CV_NOEXCEPT;
    //! conversion to another data type
    template<typename _Tp2> operator Point_<_Tp2>() const;

    //! conversion to the old-style C structures
    operator Vec<_Tp, 2>() const;

    //! dot product
    _Tp dot(const Point_& pt) const;
    //! dot product computed in double-precision arithmetics
    double ddot(const Point_& pt) const;
    //! cross-product
    double cross(const Point_& pt) const;
    //! checks whether the point is inside the specified rectangle
    bool inside(const Rect_<_Tp>& r) const;
    _Tp x; //!< x coordinate of the point
    _Tp y; //!< y coordinate of the point
};

typedef Point_<int> Point2i;
typedef Point_<int64> Point2l;
typedef Point_<float> Point2f;
typedef Point_<double> Point2d;
typedef Point2i Point;

}
GPhilo
  • 18,519
  • 9
  • 63
  • 89
  • Instead of `int32` did you mean `int32_t`? – Paul Sanders Mar 19 '19 at 17:12
  • What errors are you getting specifically? Also, can you post the typedef code? –  Mar 19 '19 at 17:16
  • In other words, what did the error say it didn't like specifically? –  Mar 19 '19 at 17:18
  • Is this in a header file or .cpp file? – Isaiah Mar 19 '19 at 17:22
  • @PaulSanders `int32` is equivalent to `int32_t` and is conditionally defined in another part of the library,I replaced it in the question with `int` because it's not relevant to this issue – GPhilo Mar 19 '19 at 17:28
  • @Chipster I added the full error message I get. What typedef are you referring to? – GPhilo Mar 19 '19 at 17:29
  • @Isaiah This is in a header file – GPhilo Mar 19 '19 at 17:30
  • What are your compiler flags? – Isaiah Mar 19 '19 at 17:35
  • @Isaiah I'm on Visual Studio, I'm not specifying compiler flags directly (and the project file was not done by me). Anything specific I should look for in the compiler flags? – GPhilo Mar 19 '19 at 17:37
  • Well I'm not sure if it's the issue, but I know in older days, compilers were unable to handle `>>` correctly with templates as it gets interpreted as the right shift operator. – Isaiah Mar 19 '19 at 17:38
  • 2
    There's nothing wrong with the code shown. The problem must be elsewhere. Is the function declaration exactly the same? – Chris Olsen Mar 19 '19 at 17:53
  • There are 3 differences: The return type is `int32`, which is a typedef of int (I changed it to int because it wasn't relevant); instead of the comment at the bottom there's a call to an overload of `write` that takes a string as value; the original signature of the function has just `string` instead of `std::string` (but we have `using namespace std;` at the beginning of the file and there are no redefinitions of string) – GPhilo Mar 19 '19 at 18:04
  • You said " (both are typedefs of cv::Point_ with a specific T)" could you show them? –  Mar 19 '19 at 18:22
  • Yeah the code you have added looks okay. –  Mar 19 '19 at 18:25
  • @Chipster they are in the linked hpp file, I'm away from my PC now, I'll add them as soon as I'm back in office – GPhilo Mar 19 '19 at 18:30
  • Hmm, again looks okay. Just for grins, how are you calling `SVIniFile::write()`? –  Mar 19 '19 at 19:13
  • Added that call (from memory, from my phone), nothing fancy happening there. I'll have a closer look at the rest of the code tomorrow, this is very confusing at the moment.. – GPhilo Mar 19 '19 at 19:37
  • Not sure this is the problem, but try write() (or whatever point type you're using) instead and see what happens. –  Mar 19 '19 at 22:04

1 Answers1

1

Since there's nothing wrong with the code shown, the problem must be with some code you have not shown. It's probably something very simple, like a missing or out-of-order #include.

You should try to create a Minimal, Complete, and Verifiable example. You'll likely find the problem while doing it.

For example, this compiles just fine on VS 2017:

#include <vector>

namespace cv {
    template<typename _Tp> class Point_ {};
    typedef Point_<int> Point2i;
}

class SVIniFile {
public:
    template<typename T>
    int write(
        const std::string& section,
        const std::string& key,
        std::vector<cv::Point_<T>>& points);
};

template<typename T>
int SVIniFile::write(
    const std::string& section,
    const std::string& key,
    std::vector<cv::Point_<T>>& points) {
    return 0;
}

int main() {
    SVIniFile svIniFile;
    std::vector<cv::Point2i> points;
    svIniFile.write("abc", "def", points);
    return 0;
}
Chris Olsen
  • 3,243
  • 1
  • 27
  • 41
  • You were right in your comment to the question (and I gave a wrong information there by accident): The cause of the error was the function signature having `string` instead of `std::string`. When I replied yesterday I seemed to remember we had `using namespace std;` at the beginning of the file, but I was mixing up the cpp and the header file. The source of the error was `string` not being defined. The fix was changing the signature to `std::string` instead. – GPhilo Mar 20 '19 at 09:40