通过typedef强制模板实例化:在g ++上成功,在Visual C ++上失败 [英] Force template instantiation via typedef : success at g++ , fail at Visual C++
问题描述
我想强制模板实例化。
下面的代码在g ++上有效(打印 1
)( http://coliru.stacked-crooked.com/a/33986d0e0d320ad4 )。
但是在Visual C ++( https:// rextester上打印错误的结果( 0
) .com / WGQG68063 )。
I want to force template instantiation.
The below code works (print 1
) at g++ ( http://coliru.stacked-crooked.com/a/33986d0e0d320ad4 ).
However, it prints wrong result (0
) at Visual C++ ( https://rextester.com/WGQG68063 ).
#include <iostream>
#include <string>
template <int& T>struct NonTypeParameter { };
//internal implementation
int lala=0;
template <typename T> struct Holder{
static int init;
};
template <typename T> int Holder<T>::init = lala++;
//tool for user
template <typename T> struct InitCRTP{
using dummy=NonTypeParameter<Holder<T>::init>;
};
class WantInit : public InitCRTP<WantInit>{};//user register easily
int main(){
std::cout << lala << std::endl;
}
这是Visual C ++编译器错误还是一种不确定的行为? br>
如果它是Visual C ++错误,如何解决(同时仍保持美观)?
Is it a Visual C++ compiler bug, or a kind of undefined behavior?
If it is Visual C++ bug, how to workaround it (while still keep it beautiful)?
编辑:按照Max Langhof(和很多人)的建议,更改类->结构。谢谢。
Change class -> struct as Max Langhof (and many people) recommended. Thank.
使用 StoryTeller的相反解决方案 和 Maxim Egorushkin 以及他们的深入讨论(谢谢!),这听起来像是C ++规则的模糊领域。
With opposite solutions from StoryTeller and Maxim Egorushkin and their in-depth discussion (thank!), this sounds like a fuzzy area of C++ rule.
如果它是Visual C ++错误,我希望这个问题一定可以报告。
If it is Visual C++ bug, I wish the issue to be certain enough to report.
此外,我仍然希望有一个不错的解决方法,因为此技术对于自定义type-id生成非常有用。显式实例化不是那么方便。
Moreover, I still wish for a nice workaround, because this technique is very shiny for custom type-id generation. Explicit instantiation is not so convenient.
注意:我授予了 Kaenbyou Rin 赏金,因为对我来说,这很容易理解。
这并不意味着其余答案不太正确或不太有用。
我仍然不确定哪个是正确的答案。读者应谨慎行事。
为了安全起见,我假设我暂时无法使用该功能。感谢大家。
Note: I awarded bounty to Kaenbyou Rin, because, for me, it is easy to understand.
It doesn't means that the rest of answers are less correct or less useful.
I am still not sure which is a correct one. Readers should proceed with caution.
For safety, I will assume that I just can't use the feature (for now). Thanks everyone.
推荐答案
肯定会涉及编译器错误。我们可以通过稍微更改 InitCRTP
来进行验证:
There is a compiler bug involved, for sure. We can verify it by changing InitCRTP
a bit:
template <typename T, typename = NonTypeParameter<Holder<T>::init>>
struct InitCRTP {
};
现在引用任何 InitCRTP< T>
专业化必须使用 Holder< T> :: init
确定第二个模板参数。反过来,这应强制实例化 Holder< T :: init
,而 VS不会实例化。
Now referring to any InitCRTP<T>
specialization must use Holder<T>::init
to determine the second template argument. This in turn should force an instantiation of Holder<T>::init
, and yet VS doesn't instantiate that.
通常,使用CRTP类作为基础应该已经实例化了该类中的所有声明,包括 dummy
。
In general, using the CRTP class as a base should have instantiated all the declarations inside the class, including that of dummy
. So that too should have worked.
我们可以进一步验证。成员函数的声明在用作基类时将与该类一起实例化。
We can verify it further. Declarations of member functions are instantiated along with the class, when used as a base:
template <typename T> struct InitCRTP{
using dummy=NonTypeParameter<Holder<T>::init>;
void dummy2(dummy);
};
还是, VC ++很固执。鉴于所有这些,以及Clang和GCC都表现出的行为,这是一个VC ++错误。
Still, VC++ is stubborn. Given all of this, and the behavior exhibited by both Clang and GCC, this is a VC++ bug.
这篇关于通过typedef强制模板实例化:在g ++上成功,在Visual C ++上失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!