目前正在开发一个涉及一些轻型 TMP 的单标题“库”,它允许用户为其类型添加自定义/特化(作为具有实际用例的自学项目)。
我在自定义位方面遇到问题。
例子
// foo_library.h
void foo(int i) {}
void foo(bool b) {}
template<typename T>
void do_something(T t)
{
foo(t);
}
// user_code.cpp: user adds specialisation for double
void foo(double d) {}
do_something(42); // ok
do_something(false); // ok
do_something(3.14); // error: do_something has not seen double overload
注意:这是关于模板实例化的——我很清楚顺序(“看到了一些东西”)在 C 系列中很重要。
知道模板实例化是惰性的,我假设模板是就地实例化的,即已经看到双重特化。显然不是这样:(
我似乎遗漏了一些基本技术或概念,因为那里有代码允许用户将他们的自定义“注入(inject)”到模板繁重的仅 header 库(std: :swap
或 nlohmann::json 浮现在脑海中)
问题:我需要什么技术来启用这种自定义注入(inject)功能,只需让用户在某个库命名空间中定义适当的函数?
我想到的事情:
将实现分散到多个 header 上,并让用户在所有自定义之后包括最后一个 header :容易出错并且可能不会扩展到玩具项目以外的任何项目
使用 section-include-guards(Symbolic C++ 这样做,但不是为了定制)将 header 分成多个部分:需要用户通过
EVERY_CUSTOMIZATION_DEFINED_HERE
宏或类似宏选择加入,不想这样。将事物包装到类模板中,希望实例化表现不同。不。
最佳答案
正如评论中所述,基本类型没有 ADL,因此您可以只添加虚拟参数(具有相关名称):
template<typename> struct Tag{};
void foo(int i, Tag<int>) { std::cout << "int:" << i << std::endl;}
void foo(bool b, Tag<bool>) {std::cout << "bool:" << b << std::endl;}
template<typename T>
void do_something(T t)
{
foo(t, Tag<T>{});
}
//user_code.cpp: 用户为double添加特化
void foo(double d, Tag<double>) {std::cout << "double:" << d << std::endl;}
int main() {
do_something(42); // ok
do_something(false); // ok
do_something(3.14); // use double overload :)
}
关于c++ - 将特化添加到单 header "library",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53361723/