2017-02-08 9 views
2
私はこのようになります便利なヘルパーメソッドを、作成した

C++なしマッチング関数テンプレートを使用して、リンカエラー

template<typename T> 
T getRandomItem(vector<T> items){ 
    if(items.isEmpty()) return nullptr; 
    int i = random(0, (int) items.size() - 1); 
    return items.at(i); 
} 

それは単にベクトルからランダムインデックスを取得し、その位置にある項目を返します。

私は最初の例をお見せしましょう:

vector<string> v = {"foo", "bar"}; 
string item = getRandomItem(v); 

コンパイラは、ここで間違って何も表示されませんが、私は非常に奇妙なリンカエラーを取得しています:

Undefined symbols for architecture armv7: 
    "std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > getRandomItem<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >)", referenced from: 

はまた、これはさえませんコンパイラを渡す:

auto v = {"foo", "bar"}; 
string item = getRandomItem(v); 

私は次のエラーを取得しています:

No matching function for call to 'getRandomItem' 

私はインラインそれを使用したい場合にも、それは動作しません。

string item = getRandomItem({"foo", "bar"}); 

私はこのようなパラメータの前に追加してみました:

string item = getRandomItem<string>({"foo", "bar"}); 

しかし、私は取得しています別のコンパイラエラー:

リンカエラーを修正するにはどうすればよいですか?ベクトルインラインでコードを変更するにはどうすればよいですか?

編集: この例はxcode 8.2.1でコンパイルされています。ランダム関数はcocos2d-xライブラリから(重要であれば)です。

EDIT2:テンプレートコードを除去した後 はコンパイル開始しました:

string getRandomItem(vector<string> items){ 
    if(items.size() == 0) return nullptr; 
    int i = random(0, (int) items.size() - 1); 
    return items.at(i); 
} 

また、私は今、この行うことができます。

string item = getRandomItem({"foo", "bar"}); 

をので、主な疑問が残る:Xcodeのコンパイラは私がすることはできません理由ここでテンプレートを使用しますか?

+0

を参照してくださいあなたのビルドコマンド(コンパイルとリンク)を表示します。また、エラーメッセージをカットしないでください。また、 'v'が' auto v = {"foo"、 "bar"};になりたいのはなぜでしょうか? –

+0

おそらく[関連](http://stackoverflow.com/questions/6429494/undefined-symbols-for-architecture-armv7)? – George

+0

'{" foo "、" bar "}'はベクトルではありません。インラインのようなものを渡すには、['std :: vector'コンストラクタ](http://en.cppreference.com/w/cpp/container/vector/vector)を見てください。コピーマネージャに注意を払わず、他のすべてを見てください( '{" foo "、" bar "}はベクトルではありません)。興味深いものを見ますか? –

答えて

2

まず最初に、{"foo", "bar"}は明らかに自動的に文字列として解釈されません。これはstd::initializer_list<const char*>と解釈されます。したがって、入力としてstd::initializer_list<const char*>を持つ関数が見つからず、std::stringを返します。だからあなたはそこでautoを使うことはできません。また、戻り値の型 "item"にもautoを使うべきです。しかし、自動とテンプレートをあまりにも多く組み合わせると、必要のない種類のすべての種類に終わることがあります。

しかし、次の行でも問題を尋ねています:if(items.isEmpty()) return nullptr;。 C++ 11標準によると、 21.4.2.9、basic_string(const charT* s, const Allocator& a = Allocator());必要条件:sはNULLポインタであってはなりません。より良い返信T()

リンカーの問題は、ビルドスクリプトに関連する可能性があります。または、すべてのファイルを定義します。

+0

あなたは正しいですか?オートは機能しません。しかしテンプレートを削除した後(私はちょうどベクトルを残しました)、関数呼び出しで{"foo"、 "bar"}を渡すことができます。私はまたisEmptyをsize()== 0に変更しました。私の編集を見てください。 – Makalele

+0

また、nullptrでプロのヒントありがとう:) – Makalele

0

私は、コードのこの部分をコンパイルすることができる午前

#include <vector> 
#include <string> 
#include <iostream> 
#include <time.h> 

using namespace std; 

template<typename T> 
T getRandomItem(vector<T> items) { 
if (items.size() == 0) return 0; 
int i = rand()%items.size()+0; 
return items.at(i); 
} 

void main() { 
srand(time(0)); 

vector<string> v = { "foo", "bar","test","test2"}; 
string item = getRandomItem(v); 
cout << item<<endl; 
} 
+0

私はまだxcodeでリンカエラーを取得しています。私はテンプレートを削除し、それを働かせるためにベクトルを残す必要があります。 – Makalele

+0

アイテムが空の場合は0を返すことはできません。 'string item = 0;'暗黙的なキャストのために動作するかもしれませんが、あなたが意味するものではありません。 'return T();'というよりむしろ。 – acraig5075

+0

acraig5075あなたは正しいですが、重要なのは私が主な問題を修正したことではありません。 – Martian

0

それを固定:

#include <iostream> 
#include <vector> 
#include <cstdlib> 
#include <ctime> 

using namespace std; 

template<typename T> 
T getRandomItem(vector<T>& items){ // note that we should pass by reference to prevent extra copy 
    if(items.size() == 0) return T(); 
    srand(time(NULL)); 
    int i = rand()%items.size()+0; 
    return items.at(i); 
} 

int main() { 
    vector<string> v; 
    v.push_back("foo"); 
    v.push_back("bar"); 
    string item = getRandomItem(v); 
    std::cout << item; 
    return 0; 
}  

here

関連する問題