Явная реализация для набора типов - PullRequest
2 голосов
/ 07 марта 2019

В моем коде обычно мне нужно написать функцию, которая принимает тип Path-like, то есть что-то, что я могу преобразовать в boost::filesystem::path, например

  • QString
  • std::string
  • const char *
  • и т. Д. *

в A.hpp

struct A
{
  template <typename PathLike> 
  void myFunction(PathLike path);
};

в A.cpp

template <typename PathLike> 
void A::myFunction(PathLike path)
{
   boost::filesystem::Path p = convertToBoostPath(path);
   //do something...
}

//Explicit instantiations needed 
template void A::myFunction(string);  
template void A::myFunction(QString);
template void A::myFunction(char const *);
//....

Проблема в том, что если я хочу сделать то же самое в другой функции B, мне нужно снова добавить явные экземпляры.Может быть, я ошибаюсь.

Ответы [ 3 ]

3 голосов
/ 07 марта 2019

Вместо написания шаблонной функции, которая принимает любую PathLike, а также выполняет реальную работу, напишите шаблонную функцию, которая принимает любую PathLike, преобразует ее в boost::filesystem::Path, как показано, затем вызывает не шаблонную функцию ( чье определение может быть в .cpp), которое будет выполнять реальную работу.

В A.hpp:

class A
{
public:
  template <typename PathLike> 
  void myFunction(PathLike path);

private:
  void myFunctionImpl(boost::filesystem::Path path);
};


template <typename PathLike> 
void A::myFunction(PathLike path)
{
  myFunctionImpl(convertToBoostPath(path));
}

In A.cpp:

void A::myFunctionImpl(boost::filesystem::Path path)
{
  // do something...
}

Это дает дополнительное преимущество: неправильное использование интерфейса приводит к ошибкам компилятора, а не к ошибкам компоновщика.

1 голос
/ 07 марта 2019

Как насчет создания класса PathLike и его использования:

class PathLike
{
public:
    explicit PathLike(const QString& path) : mPath(convertToBoostPath(path)) {}
    explicit PathLike(const std::string& path) : mPath(convertToBoostPath(path)) {}
    explicit PathLike(const char* path) : mPath(convertToBoostPath(path)) {}
    PathLike(const boost::filesystem::path& path) : mPath(path) {}

    const boost::filesystem::path& get() const { return mPath;}
    operator const boost::filesystem::path&() const { return mPath;}
private:
    boost::filesystem::path mPath;
};

(я отмечаю другой конструктор явно для продвижения filesystem::path, но вы можете добавить / удалить explicit).

А потом:

struct A
{
    void myFunction(PathLike path)
    {
       boost::filesystem::path p = path;
       //do something...
    }
};
0 голосов
/ 07 марта 2019

Один из способов явного создания экземпляра шаблона функции для пакета типов - это получение адреса каждого экземпляра функции.Например:

template<class... Ts>
void instantiate_myFunction() {
    auto f = [](auto&&) { return 1; };
    auto initializer_list = { f(&A::myFunction<Ts>)...  };
    static_cast<void>(initializer_list);
}

int main() {
    instantiate_myFunction<std::string, char const*>();
}
...