一组类型的显式实例化

时间:2019-03-07 16:47:07

标签: c++ templates metaprogramming

通常在我的代码中,我必须编写一个具有“类似路径”类型的函数,即可以转换为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 个答案:

答案 0 :(得分:3)

编写一个接受任何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));
}

A.cpp中:

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

这还有一个好处,就是滥用接口会导致编译器错误,而不是链接器错误。

答案 1 :(得分:1)

如何创建类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...
    }
};

答案 2 :(得分:0)

显式实例化一组类型的函数模板的一种方法是获取每个函数实例化的地址。例如:

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*>();
}