-1

In my header file, I have two different kind of objects ImageFrame and `PointCloudFrame. These are then defined with a std::variant as such

struct ImageFrame{

};

struct PointCloudFrame{

};

using SensorFrame = std::variant<std::shared_ptr<ImageFrame>,
                                std::shared_ptr<PointCloudFrame>>;

I need to write a template method for both these objects so I did it like this in the headerfile:

template<class T>
std::string getFrameBin(const T& frame);

And in the cpp file

template <class ImageFrame>
std::string getFrameBin(const ImageFrame& image_frame)
{
  std::string x;
  return x;
}

template <class PointCloudFrame>
std::string getFrameBin(const PointCloudFrame& cloud_frame)
{
  std::string x;
  return x;
}

However, I get the error relating to: error: redefinition of 'template<class PointCloudFrame> std::string

What am I doing wrong? Is there a more elegant way to do this to make use of the SensorFrame object

raaj
  • 2,869
  • 4
  • 38
  • 58

4 Answers4

4

This doesn't need to be a template. It's just overloading:

std::string getFrameBin(const ImageFrame&) {
    // do ImageFrame stuff
}

std::string getFrameBin(const PointCloudFrame&) {
    // do PointCloudFrame stuff
}

Declare the two functions in a header file and implement them in a .cpp file.

Pete Becker
  • 74,985
  • 8
  • 76
  • 165
2
template <class ImageFrame>
std::string getFrameBin(const ImageFrame& image_frame)
{
  std::string x;
  return x;
}

Means the same thing as

template <class T>
std::string getFrameBin(const T& image_frame)
{
  std::string x;
  return x;
}

So you are defining your template twice. If you mean to make specializations for the templated function, the syntax would be:

template <>
std::string getFrameBin(const ImageFrame& image_frame)
{
  std::string x;
  return x;
}

template <>
std::string getFrameBin(const PointCloudFrame& cloud_frame)
{
  std::string x;
  return x;
}
qz-
  • 674
  • 1
  • 4
  • 14
1

Here's how I would do it:

#include <cstdio>
#include <memory>
#include <variant>

struct ImageFrame {};

struct PointCloudFrame {};

using SensorFrame =
    std::variant<std::shared_ptr<ImageFrame>, std::shared_ptr<PointCloudFrame>>;

struct Visitor {
  void operator()(std::shared_ptr<ImageFrame> const&) const {
    // Use image frame
    std::puts("Visiting image");
  }
  void operator()(std::shared_ptr<PointCloudFrame> const&) const {
    // Use point cloud
    std::puts("Visiting point cloud");
  }
};

int main() {
  SensorFrame frame = std::make_shared<ImageFrame>();
  std::visit(Visitor{}, frame);
  frame = std::make_shared<PointCloudFrame>();
  std::visit(Visitor{}, frame);
}
Aykhan Hagverdili
  • 28,141
  • 6
  • 41
  • 93
0

You defined the same template twice. The parameter name is just a name. Compare your code to:

void foo(int x) {}

void foo(int y) {}

Similar to how you defined the same template twice, this is two definitions for the same function.

When the implementation is identical, it actually is a good case for templates, but define it only once:

template <class T>
std::string getFrameBin(const T& cloud_frame)
{
  std::string x;
  return x;
}

Then call it with either type as parameter and the template parameter will be deduced from the function parameter. When the implementation is not identical, you should rather provide two overloads. If you still want to stay with the template, you can specialize it as outlined in the other answer.

Also read this: Why can templates only be implemented in the header file?

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185