1

本から - C++ Templates: The Complete Guide by David, Nicolai

したがって、テンプレートは 2 回コンパイルされます。

  1. インスタンス化を行わない場合、テンプレート コード自体の構文が正しいかどうかがチェックされます。セミコロンがないなどの構文エラーが検出されます。
  2. インスタンス化の時点で、テンプレート コードがチェックされ、すべての呼び出しが有効であることが確認されます。サポートされていない関数呼び出しなど、無効な呼び出しが検出されます。

Keeping the first point, I wrote -

template<typename T>
void foo( T x)
{
   some illegal text
}

int main()
{
   return 0;
}

It build fine on Visual Studio 2010 with out any warnings with optimizations turned off. How ever, it failed on gcc-4.3.4. Which one is complying to the C++ standard ? Is it mandatory for template code to get compiled even with out template instantiation ?

4

2 に答える 2

7

問題のプログラムは形式が正しくありませんが、この場合、C++ 標準は診断を必要としないため、Visual Studio と GCC の両方が準拠した方法で動作しています。C++03 標準の §14.6/7 から (強調鉱山):

どの名前が型名であるかを知ることで、すべてのテンプレート定義の構文をチェックできます。有効な特殊化を生成できるテンプレート定義に対しては、診断は発行されません。テンプレート定義に対して有効な特殊化を生成できず、そのテンプレートがインスタンス化されていない場合、テンプレート定義は不適切な形式であり、診断は必要ありません。非依存の名前で使用される型が、テンプレートが定義された時点では不完全であるが、インスタンス化が行われた時点では完全である場合、およびその型の完全性がプログラムの良し悪しに影響する場合プログラムのセマンティクスが形成されているか影響を与えている場合、プログラムの形式が正しくありません。診断は必要ありません。[注:テンプレートがインスタンス化されている場合、この標準の他のルールに従ってエラーが診断されます。これらのエラーがいつ診断されるかは、実装の品質の問題です。] [例:

int j;
template<class T> class X {
    // ...
    void f(T t, int i, char* p)
    {
        t = i; // diagnosed if X::f is instantiated
               // and the assignment to t is an error
        p = i; // may be diagnosed even if X::f is
               // not instantiated
        p = j; // may be diagnosed even if X::f is
               // not instantiated
    }
    void g(T t) {
        +; //may be diagnosed even if X::g is
           // not instantiated
    }
};

—<em>例の終わり]

于 2012-04-25T21:41:28.070 に答える
0

The book you're looking at seems to reflect (mostly) that author's observations about how compilers really work, not the requirement(s) of the standard. The standard doesn't really say much to give extra leniency to a compiler about ill-formed code inside a template, just because it's not instantiated.

At the same time, the book is correct that there are some things a compiler really can't do much about checking until it's instantiated. For example, you might use a dependent name as the name of a function (or invoke it like a function, anyway -- if it's functor instead that would be fine too). If you instantiate that template over a class where it is a function, fine and well. If you instantiate it over a class where it's really an int, attempting to call it will undoubtedly fail. Until you've instantiated it, the compiler can't tell which is which though.

This is a large part of what concepts were really intended to add to C++. You could directly specify (for example) that template X will invoke T::y like a function. Then the compiler could compare the content of the template with the declarations in the concept, and determine whether the body of the template fit with the declaration in the concept or not. In the other direction, the compiler only needed to compare a class (or whatever) to the concept to determine whether instantiating that template would work. If it wasn't going to work, it could report the error directly as a violation of the relevant concept (as it is now, it tries to instantiate the template, and you frequently get some strange error message that indicates the real problem poorly, if at all).

于 2012-04-25T21:38:15.767 に答える