Sto*_*ica 5 c++ sfinae template-meta-programming
所以我正在设计一种my_numeric_cast函数来限制使用我正在编写的框架时可用的转换类型.
做类似的事情非常简单
template<typename To, typename From>
constexpr To my_numeric_cast(From);
template<>
constexpr float my_numeric_cast<float, int>(int i) { return i; }
Run Code Online (Sandbox Code Playgroud)
哪个工作,只允许在使用铸件时从整体铸造到浮子.并且每当尝试不在白名单中的演员表时产生链接错误.
但是,我真的想让这个编译错误,以更快地捕获滥用.
如何使基本模板体有效,在实例化时期望?
你不能编写一个模板函数专门化,没有模板参数使得主体在C++中有效.如果这样做的结果是形成错误的程序,不需要诊断.这包括主要专业化.
所以这里的大部分答案都是未定义的行为.它们可能有效,但它们不是有效的C++.它们可能在今天工作,但在库升级后,编译器升级或不同的构建目标可能会以完全不同且令人惊讶的方式失败.依靠UB没有充分理由是一个坏主意.
从好的方面来说,我们可以取消模板专业化并一举解决您的问题:
template<class T>struct tag_t{}; // may need `constexpr tag_t(){}` on some compilers
template<class T>constexpr tag_t<T> tag{};
template<class T, class F>
constexpr T my_numeric_cast(F, tag_t<F>)=delete; // generates compile time error
constexpr float my_numeric_cast(int i, tag_t<float>) { return i; } // not a template! Could be if you want it to be.
template<typename To, typename From>
constexpr To my_numeric_cast(From f){
return my_numeric_cast(f, tag<To>);
}
Run Code Online (Sandbox Code Playgroud)
并做了.
=delete生成友好的消息.计划形成良好.实施演员表不再是专业化.您甚至可以在启用ADL的类型的命名空间中实现它.
如果您解决了模板功能专业化的问题,请重新考虑.它们很脆弱,不像类模板特化或函数重载那样工作(看起来像它们两个!),通常不是最好的解决方案.有一些例外,它可能是一个好主意,但它们是非常罕见的,并且考虑到它们避免古怪特征的罕见性可能仍然值得.