2016-04-12 12 views
0

C++のconstメンバ関数、非型テンプレートや外部シンボル

#pragma once 
class functions { 
public: 
    static const int addition(const int&, const int&); 
    static const int product(const int&, const int&); 
}; 

functions.cpp

私も、私が選択する機能のどの定義するプログラム設定のためのセクションを作成しました
#include "functions.h" 
const int functions::addition(const int& op1, const int& op2) { 
    return op1 + op2; 
} 
const int functions::product(const int& op1, const int& op2) { 
    return op1 * op2; 
} 

次のサンプルを使用して期待通り

constants.h

#pragma once 
const int modulus = 10; 
extern const int(*operation)(const int&, const int&); 

constants.cpp

#include "constants.h" 
#include "functions.h" 
const int(*operation)(const int&, const int&) = &functions::addition; 

は、このコードは動作します:

main.cppに

#include <iostream> 
#include "constants.h" 
int main() { 
    int a = 7, b = 4; 
    std::cout << operation(a,b) % modulus << std::endl; 
} 

問題は、あります今私はfuをparametrizeしたいと思います以下のような非型テンプレートを使用してnctionsのほか、製品、:

functions.h

#pragma once 
class functions { 
public: 
    template<const int&> static const int addition(const int&, const int&); 
}; 

どんなに私が適応しようとする方法をfunctions.cpp

#include "functions.h" 
template<const int& sub> const int functions::addition(const int& op1, const int& op2) { 
    return op1 + op2 - sub; 
} 

後でコードブレーク、他のファイル。私は合理的に(そして無意識のうちに)想像できるすべてをやった。

定数*。でコードを書き直す方法についてのヘルプは非常に高く評価されます。

+0

サイドノート:あなたはファーストクラスは必要ありません。あなたの関数に別の名前空間が必要な場合は、名前空間を使います。 – molbdnilo

+0

あなたのアドバイスをありがとうございますが、クラスは、指定された機能を扱う他の機能をグループ化しています。彼らはこの問題で何の役割も果たしていないので、私はそれらを最小限の例から除外することに決めました。 – jvier

+0

私はそれがどう重要であるかわかりません。静的メンバーだけを持つクラスはJava/C#/ Smalltalkのものです。 – molbdnilo

答えて

0

テンプレートはコンパイル時にインスタンス化され、その定義は既知でなければならないため、ヘッダーにテンプレート定義が必要です。

でも、intはパラメータではなく、const int&となります。
これは、コンパイル時に識別情報(つまり位置)を特定できる左辺値でインスタンス化する必要があることを意味します。
これは、パラメータが外部リンケージを持つ変数でなければならないことを意味します。一時変数やローカル変数ではありません。言い換えれば

extern int x; 

void foo() 
{ 
    addition<1>(2,3); // Not good; not an lvalue 
    const int y = 1; 
    addition<y>(2,3); // Not good; no linkage 
    addition<x>(2,3); // Good 
} 

あなたはおそらく代わりにtemplate<int sub>を使用します。

(別のサイドノート:プリミティブ型へのconst参照は無意味です彼らはすべてのオーバーヘッドを追加するだけです。)

+0

ありがとうございます!私は変数xをどこで定義するか決めようとしています。参照をプリミティブ型に渡す場合は、元のコードの場合とは異なります。追加:私はintとして再定義を検討しているが、私は他のエラーの原因を思い出すことができます。乾杯。 – jvier

+0

テンプレートを使用することは未解決の外部シンボルと同じ理由でコンパイルされません。 – jvier

+0

@jvier定義をヘッダに入れましたか? ([ここ](http://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file)を参照してください。) – molbdnilo

0

テンプレートの定義はインスタンス化中に、コンパイラに見えること、または明示的にインスタンス化しなければならないのいずれか。整数テンプレートのすべての可能なバージョンを明示的にインスタンス化できることは非常に疑問なので、ヘッダにdefginitonsを入れました。

operationsの問題があります。関数ポインタであるため、テンプレートのインスタンス(特定の整数テンプレートを使用してインスタンス化されたインスタンス)を指すことができます。それはまったく使えません。

デザインを再考することをおすすめします。

+0

ありがとうございます!私は常にデザインを考え直していますが、操作を関数テンプレートのインスタンスとして定義することをお勧めします。しかし、私が何をしても、コンパイル時に外部リンケージの問題が投げかけられました。 – jvier

+0

私はあなたのコメントを深く読んでおり、それは啓発しています。だから私は、明示的なインスタンス化は再帰的なテンプレート(私の知識があれば "variadic")を持つサンプルの1つでなければならないと思います。ありがとう! – jvier

関連する問題