在SO上阅读问题,评论和答案,我一直听说MSVC没有正确地实现两阶段模板查找/实例化.
据我所知,到目前为止,MSVC++只对模板类和函数进行了基本的语法检查,并没有检查模板中使用的名称是否至少被声明了或者沿着这些行.
它是否正确?我错过了什么?
以下C++代码无法编译,例如使用g ++ - 4.7或clang ++ - 3.2:
struct Bar {};
template<typename T>
void foo(T t, Bar bar) {
t.compiler_does_not_care();
bar.nonexistent_method();
}
int main() {}
Run Code Online (Sandbox Code Playgroud)
为什么编译器检查模板函数foo的代码是否具有语义正确性(他们可以在哪里),即使它从未实例化过?这个标准是否合规?
我正在研究两个阶段名称查找.一个非常合乎逻辑的解释表明,其中一个主要原因是遵循C++哲学尽早捕获错误.
我的问题是为什么这种哲学不遵循非模板化方法.而不是检查何时以及是否调用该方法,为什么不在实例化模板化类时检查阶段2中的所有非模板化方法?
例如:
template <class T>
struct X {
auto foo() // non-templated (important)
{
T t{};
return t.non_existing();
}
};
int main()
{
X<int> x; // (1) this compiles OK.
// somewhere is a galaxy far far away,
// maybe deep inside some unrelated code
x.foo(); // (2) the error is here
}
Run Code Online (Sandbox Code Playgroud)
如果你从不写(2)程序编译并运行没有任何问题,虽然foo对于实例化是非法的X<int>.
无论你是否打过电话,我认为第(1)行应该产生错误foo.
在编写模板化类时,这可以让错过一个错误直到你最终调用有问题的方法(2),而不是在实例化模板化类(1)时得到错误.
另外,健全性检查:如果我实例化X<int>(1)但从不调用X<int>::foo(2),代码是否有效?或者它是否像"形成不良,无需诊断"?如果是后者,那么这是更早发现错误的原因.
目前我正在尝试为<<我正在处理的类重载插入操作符.出于某种原因,我将其分成两个函数,并从另一个函数中调用一个函数.切换到模板后,它不再起作用了.在查找问题之后,我发现了两个阶段查找和背后的一些推理.
基本上,我试图做的是以下内容:
template <typename Foo, typename Bar>
class MyClass {
public:
using foo_t = Foo;
using bar_t = Bar;
bar_t some_func() const { /* do something */ }
};
/* Level 2 operator */
template <typename Foo, typename Bar>
std::ostream& operator<<(std::ostream& out, const typename MyClass<Foo,Bar>::bar_t& bar) {
return out << some_other_func(bar);
}
/* Level 1 operator calls level 2 operator */
template <typename Foo, typename Bar>
std::ostream& operator<<(std::ostream& out, const MyClass<Foo,Bar>& myClass) {
return …Run Code Online (Sandbox Code Playgroud)