vol*_*evo 9 c++ templates boost template-specialization
有没有更好的方法来做到以下几点?
#include <iostream>
template <typename T>
T Bar();
template <>
int Bar<int>() { return 3; }
// Potentially other specialisations
int main()
{
std::cout << Bar<int>() << std::endl; // This should work
std::cout << Bar<float>() << std::endl; // This should fail
}
Run Code Online (Sandbox Code Playgroud)
该解决方案的问题在于它(可理解地)链接时间与"未定义的浮点引用Bar<float>()"等失败.这可能会让其他开发人员感到困惑,因为他们可能怀疑实现文件没有被链接.
我知道另一种可能的解决方案:
template <typename T>
T Bar() { BOOST_STATIC_ASSERT(sizeof(T) == 0); }
Run Code Online (Sandbox Code Playgroud)
这会在Bar<float>()请求时导致编译器错误,正是我想要的.但是,我担心技术上编译器可能会拒绝这一点,就像gcc拒绝一样,BOOST_STATIC_ASSERT(false)因为它知道无论模板参数如何都会失败,因为sizeof(T)它永远不会为零.
总之,我想知道是否:
BOOST_STATIC_ASSERT(sizeof(T))实际上没有实例化也不会失败.这可能有效:
template <typename T>
T Bar() {
T::ERROR_invalid_template_argument_;
}
template <>
int Bar<int>() { return 3; }
Run Code Online (Sandbox Code Playgroud)
如果您害怕使用0,您也可以使用最大尺寸:
static_assert(sizeof(T) == -1, "No specialization");
Run Code Online (Sandbox Code Playgroud)
BOOST_STATIC_ASSERT(sizeof(T) == 0);在实例化模板之前不允许失败,所以我只会这样做。你是对的,BOOST_STATIC_ASSERT(false);每次都会触发。
其原因与两阶段名称查找有关。这本质上是这样的:编译模板时,它会被编译两次。编译器第一次看到模板时,它会编译除依赖于模板参数的表达式之外的所有内容,一旦知道模板参数,就会进行第二次编译,从而完全编译实例化。
\n\n这就是为什么BOOST_STATIC_ASSERT(false);总是失败的原因:这里没有任何依赖项,并且断言会立即处理,就好像该函数根本不是模板一样。(请注意,MSVC 没有实现两阶段查找,因此在实例化时会错误地失败。)相反,因为T是依赖的 (\xc2\xa714.6.2.1),所以BOOST_STATIC_ASSERT(sizeof(T) == 0);是依赖的,并且不允许在检查之前进行检查模板被实例化。(在上面它总是会失败。)
如果编译器试图深思熟虑并提前失败,那么它将是不合格的。你应该能够依赖这个东西。也就是说,如果恐惧战胜了你,那么真正让它等待是微不足道的:
\n\nBOOST_STATIC_ASSERT(sizeof(typename T::please_use_specializations) == 0);\nRun Code Online (Sandbox Code Playgroud)\n\n这既保证会失败,又不可能让编译器提前正确地“智能”失败。
\n