c++templateslexical-cast

Overloading lexical_Cast with a templated class


I'm trying to extend lexical_cast to handle string->cv::Point conversions, with code like so:

#include <iostream>
#include <opencv2/opencv.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/split.hpp>

namespace boost {
  template<>
    cv::Point2f lexical_cast(const std::string &str) {
      std::vector<std::string> parts;
      boost::split(parts, str, boost::is_any_of(","));
      cv::Point2f R;
      R.x = boost::lexical_cast<float>(parts[0]);
      R.y = boost::lexical_cast<float>(parts[1]);
      return R;
    }
}

int main(int argc, char **argv) {
  auto p = boost::lexical_cast<cv::Point2f>(std::string("1,2"));
  std::cout << "p = " << p << std::endl;
  return 0;
}

And it works great.. However, cv::Point2f is actually cv::Point_<T> where T can be int, float, double, etc. I can't find anyway to expose that templated arg to the lexical_cast, so that I can have a single lexical_cast function that can handle all cv::Point_<T> types.


Solution

  • template <typename T>
    struct point_type {};
    
    template <typename T>
    struct point_type<cv::Point_<T>> { using type = T; };
    
    namespace boost {
      template <typename T, typename U = typename point_type<T>::type>
        T lexical_cast(const std::string &str)
        {
          std::vector<std::string> parts;
          boost::split(parts, str, boost::is_any_of(","));
          T R;
          R.x = boost::lexical_cast<U>(parts[0]);
          R.y = boost::lexical_cast<U>(parts[1]);
          return R;
        }
    }
    

    DEMO


    The previous, a little more complicated solution, if you don't like this implicit second template parameter of lexical_cast:

    #include <type_traits>
    
    template <typename T>
    struct is_point : std::false_type {};
    
    template <typename T>
    struct is_point<cv::Point_<T>> : std::true_type {};
    
    template <typename T>
    struct point_type;
    
    template <typename T>
    struct point_type<cv::Point_<T>> { using type = T; };
    
    namespace boost {
      template <typename T>
        auto lexical_cast(const std::string &str)
          -> typename std::enable_if<is_point<T>::value, T>::type
        {
          std::vector<std::string> parts;
          boost::split(parts, str, boost::is_any_of(","));
          using U = typename point_type<T>::type;
          T R;
          R.x = boost::lexical_cast<U>(parts[0]);
          R.y = boost::lexical_cast<U>(parts[1]);
          return R;
        }
    }
    

    DEMO 2