質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

3回答

1815閲覧

main.cppから複数のファイルに分けるとエラーが出る

退会済みユーザー

退会済みユーザー

総合スコア0

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

1クリップ

投稿2020/04/23 00:52

編集2020/04/23 00:56

C++に慣れるために、線形探索, 二部探索を自作して標準ライブラリのものと比べています。
main.cppにまとめて書いていた関数をsearch_algorithms.h / search_algorithms.cppに分けたのですが、... is used but not defined in this translation unit, and cannot be defined in any other translation unit because its type does not have linkageというエラーが出ます。
ほとんどmain.cpp以外に分けて書いたことがないので、かなり初歩的なミスをしているかもしれませんが、よろしくお願いします。

Wandboxへのリンク↓
正常に動くコード / エラーが出る分割したコード

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

普通のテンプレートであれば、main.cpp で使いたい型のインスタンスを search_algorithms.cpp で明示的に生成すればいいのですが、C++ のラムダは一つ一つ型が違う (確か...) ので、テンプレートにする場合はヘッダに実装を書くか、実装を別ファイルにしたいなら std::function でラップすればいいと思います。

search_algorithms.h

diff

1 namespace my { 2 3-template<class Predicate> 4+typedef std::function<bool(int)> Predicate; 5 Iterator SequentialSearch(Iterator begin, Iterator end, Predicate pred); 6 7-template<class Compare> 8+typedef std::function<bool(int)> Compare; 9 Iterator BinarySearch(Iterator begin, Iterator end, Compare comp); 10 }

search_algorithms.cpp

diff

1 #include <functional> 2+#include <vector> 3 #include "search_algorithms.h" 4 5 namespace my { 6-template<class Predicate> 7 Iterator SequentialSearch(Iterator begin, Iterator end, Predicate pred) { 8 // 略 9 } 10 11-template<class Compare> 12 Iterator BinarySearch(Iterator begin, Iterator end, Compare comp) { 13 // 略 14 }

投稿2020/04/23 02:14

編集2020/04/23 02:22
hoshi-takanori

総合スコア7901

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

C++のtemplate関数/クラスはtemplate外から利用された時にはじめて実体化されます。
そのせいもあって、宣言と実装をわけるのは大変です。

今回は、ラムダ式の型が翻訳単位に縛られているせいで、テンプレート関数へ渡せる型にならない事が問題となっています。

対処方法としては

  • 宣言と実装を一緒にする。

つまりはsearch_algorithms.hsearch_algorithms.cppの内容を書いてしまう。

  • templateではなくstd::functionを用いる。

c++

1namespace my { 2using Predicate = std::function<bool(int)>; 3using Compare = std::function<int(int)>; 4Iterator SequentialSearch(Iterator begin, Iterator end, const Predicate& pred); 5Iterator BinarySearch(Iterator begin, Iterator end, const Compare& comp); 6}
  • std::functionを明示的に実体化する。

main.cpp側のテンプレートに渡しているラムダ式をすべてstd::function([&target](const int &cur) { return cur == target; })のように変換し
search_algorithms.cpp

c++

1template Iterator SequentialSearch(Iterator begin, Iterator end, std::function<bool(const int&)> pred); 2template Iterator BinarySearch(Iterator begin, Iterator end, std::function<int(const int&)> comp);

を記述しておく

テンプレート関数としての利点がなくなりますし、ヘッダにテンプレート関数の実装を書くのが一番いいように思います。

投稿2020/04/23 02:39

編集2020/04/23 04:04
asm

総合スコア15149

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2020/04/23 03:06

ありがとうございます。 ヘッダに実装を書くのはあまりよろしくないとされているようですが、こういうtemplate関数のときは大抵書いてしまうものなのでしょうか? 練習のコードなので気にするほどのものではないのは確かですが...
asm

2020/04/23 04:10

通常の関数の場合は、確かにヘッダに実装を書いてしまうと不都合がありますが templateの場合は分けたほうが不都合なので、通常はヘッダに実装を書きます。 STLやboostも大抵の場合はヘッダに書かれています
guest

0

分割コンパイルのとき、テンプレートの定義はヘッダファイルに記載する必要があります。外部関数と異なり、テンプレートはコンパイル時に展開されるからです。

投稿2020/04/23 01:44

majiponi

総合スコア1722

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問