0

この投稿で説明されている方法を使用して、「名前空間以外のスコープでの明示的な特殊化」エラーを修正しようとしています。そのため、テンプレート化された関数を別の名前空間に移動し、クラスからこれらの関数を呼び出しています(以下のコードを参照)。

コードがコンパイルされるようになりましたが、名前空間内のすべての関数に対して「main.objですでに定義されている」リンカーエラーが発生します。一番上に追加する#ifndef STYLE_Hと、名前空間が複数回含まれるのを防ぐことができると思いましたか、それとも何かが足りませんか?このエラーを修正するにはどうすればよいですか?

以下は私のコードです(簡略化):

#ifndef STYLE_H
#define STYLE_H

namespace hanzi {

namespace styleUtil {

    template <class T> 
    T get(const QString& name, T defaultValue = T(), const Style* style = NULL, const Style* baseStyle = NULL) {    
        // ...
    }

    template <> 
    QColor get<QColor>(const QString& name, QColor defaultValue, const Style* style, const Style* baseStyle) {  
        // ...
    }

    template <> 
    ImagingEffect get<ImagingEffect>(const QString& name, ImagingEffect defaultValue, const Style* style, const Style* baseStyle) { 
        // ...
    }

}

class Style : public QObject {

    Q_OBJECT

public:

    explicit Style(const QString& filePath);

    template <class T> 
    T get(const QString& name, T defaultValue = T()) const {
        return styleUtil::get<T>(name, defaultValue, this, baseStyle_);
    };

};

}

#endif // STYLE_H
4

2 に答える 2

2

関数テンプレートの完全な特殊化は、もはやテンプレートではありません。それは関数です。

そのため、ヘッダーで定義する場合は、キーワードを追加する必要がありますinline

inlineC ++の「単一定義規則」(ODR)の動作を変更します。基本的にinline、関数は、それが使用されるすべての変換単位で定義されている必要があり、それらの定義は事実上等しくなければなりません。どちらも、定義をヘッダーファイルに配置することで実現されます。

inline最適化に関するヒントとしても役立ちますが、その2番目の意味は保証されません。

また、この回答が誤解を招かないように、関数テンプレートの部分的な特殊化などはありません。

于 2012-03-17T09:43:09.200 に答える
2

元のエラーについては、

「名前空間以外のスコープでの明示的な特殊化」エラーを修正しようとしています

このエラーが意味するのは、クラス定義内でメンバー関数テンプレートの特殊化を定義できないことです。つまり、次のことは違法です。

struct Bar
{
    template <typename T> void boo() { }
    // template <> void boo<char>() { boo<int>(); }  // Error! Cannot specialize here
};

ただし、これは、特殊化をクラス定義の外に配置するだけで解決されます。

template <> void Bar::boo<char>() { boo<int>(); }  // Good.

(スペシャライゼーションの後者の位置は、たとえばグローバルスコープでの「名前空間スコープで」です。これは、エラーメッセージが指示したかったことです。)

于 2012-03-17T09:42:27.377 に答える