什么是创建一个只有专业化功能模板的最佳方式? [英] What is the best way to create a specialization-only function template?

查看:113
本文介绍了什么是创建一个只有专业化功能模板的最佳方式?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有没有更好的办法来做到以下几点?

 的#include<&iostream的GT;模板< typename的T>
T吧();模板<>
INT酒吧和LT; INT>(){返回3; }//其他可能的特诠释的main()
{
    性病::法院LT&;<酒吧和LT; INT>()<<的std :: ENDL; //这应该工作
    性病::法院LT&;<酒吧和LT;浮动>()<<的std :: ENDL; //这应该失败
}

这个解决方案的问题是,它的(可以理解)链接时使用失败未定义参考浮动酒吧<浮动>()等。这对于其他开发混淆,因为它们可能会怀疑一个实现文件不被链接

我知道另一个潜在的解决方案:

 模板< typename的T>
T吧(){BOOST_STATIC_ASSERT(的sizeof(T)== 0); }

这会导致一个编译器错误时,酒吧及LT; 要求(),正是我想要的;浮动过夜。但是,我担心在技术上编译器可能会拒绝这就像GCC拒绝 BOOST_STATIC_ASSERT(假),因为它知道,它会不管模板参数的失败,因为的sizeof(T)可以的从不的是零。

总之,我想知道是否:


  1. 还有另一种方式来做到这一点。

  2. 我是错误的, BOOST_STATIC_ASSERT(的sizeof(T))实际上不能不没有实例化。

  3. 的唯一方法就是让这成为一个链接器错误同上。


解决方案

BOOST_STATIC_ASSERT(的sizeof(T)== 0); 是不允许失败,直到模板被实例化,所以我只想做一个。你是正确的 BOOST_STATIC_ASSERT(假); 触发每次


这样做的原因有两相名称查找做。这实质上是以下情况:当模板被编译,它的编译两次。第一次compielr看到它编译模板的所有的除了依赖模板参数除权pressions,一旦模板参数是已知的,完全编译实例化第二次汇编发生。

这就是为什么 BOOST_STATIC_ASSERT(假); 总是会失败:这里没有什么是依赖,并断言立即处理,因为如果该函数不是一个模板,在所有。 (需要注意的是MSVC不执行两阶段查找,因此失败的实例,不正确。)相反,因为 T 依赖(§14.6.2.1), BOOST_STATIC_ASSERT(的sizeof(T)== 0); 是相关的,并且不允许进行检查,直至模板实例。 (根据它在哪里总是会失败。)

如果编译器试图周到和提前失败,那么,这将是不合格的。你想成为能够依靠这个东西。这就是说,如果怕得到最好的,你是微不足道的的真正的让它等待:

  BOOST_STATIC_ASSERT(sizeof的(typename的T :: please_use_specializations)== 0);

这是双方注定要失败,而不可能的编译器来正确地潇洒地失败的时间提前。

Is there a better way to do the following?

#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
}

The problem with this solution is that it fails at (understandably) link time with "undefined reference to float Bar<float>()" or the like. This can be confusing for other developers as they may suspect an implementation file is not being linked.

I do know another potential solution:

template <typename T>
T Bar() { BOOST_STATIC_ASSERT(sizeof(T) == 0); }

This causes a compiler error when Bar<float>() is requested, exactly what I want. However, I'm concerned that technically a compiler may reject this just as gcc rejects BOOST_STATIC_ASSERT(false) because it knows that it will fail regardless of the template parameter, since sizeof(T) can never be zero.

In summary, I want to know whether:

  1. There is another way to do this.
  2. I'm mistaken and BOOST_STATIC_ASSERT(sizeof(T)) actually can't fail without instantiation.
  3. The only way is to let this be a linker error as above.

解决方案

BOOST_STATIC_ASSERT(sizeof(T) == 0); isn't allowed to fail until the template is instantiated, so I would just do that one. You are correct that BOOST_STATIC_ASSERT(false); triggers each time.


The reason for this has to do with two-phase name lookup. This is, essentially, the following: when a template is compiled, it's compiled twice. The first time a compielr sees a template it compiles everything except the expressions dependent on template parameters, and the second compilation happens once the template parameter is known, compiling the instantiation fully.

This is why BOOST_STATIC_ASSERT(false); will fail always: nothing here is dependent and the assert is processed immediately, as if the function weren't a template at all. (Note that MSVC does not implement two-phase look-up, so this fails at instantiation, incorrectly.) Contrarily, because T is dependent (§14.6.2.1), BOOST_STATIC_ASSERT(sizeof(T) == 0); is dependent, and is not allowed to be checked until the template is instantiated. (Where upon it will always fail.)

If a compiler tries to be thoughtful and fail it ahead of time, it would be non-conforming. You're suppose to be able to rely on this stuff. That said, if fear gets the best of you it's trivial to really make it wait:

BOOST_STATIC_ASSERT(sizeof(typename T::please_use_specializations) == 0);

This is both guaranteed to fail, and impossible for a compiler to correctly "smartly" fail ahead of time.

这篇关于什么是创建一个只有专业化功能模板的最佳方式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆