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

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

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

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

Q&A

解決済

5回答

1158閲覧

C++の型の解決ができなくて困っています。

GrayWingAliance

総合スコア218

C++

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

0グッド

0クリップ

投稿2019/07/03 16:19

編集2019/07/04 00:32

cpp

1#include <iostream> 2using namespace std 3 4void sort_pointers (void **ar, int n, int(*cmp)(const void *, const void *));

上記のようなconst void *型の引数を持つ関数ポインタにおいて
int func (int, int)を代入するにはどうすればいいんでしょうか?
main関数にて

cpp

1int main() { 2 int nums[2] = {1, 2} 3 int (*cmp)(const void *, const void *); 4 cmp = int_cmp; 5 sort_pointers(nums, 2, cmp); 6 return 0; 7}

のように使いたいです…
つ・・・伝われ・・・!

あと、void **arのような二重の値参照にはどんな意味なのですか?
調べても出てこない…。

もし、わかる方いらっしゃったらお願いいたします。

#追記
const void *型の引数はどんな型でも使用できるという意味合いだと認識しておりまして、cmp関数を引数に取っているのは、int型であろうとchar型であろうと比較のための関数を作成してあげれば、ソートができるから、だと認識しています。

cpp

1int int_cmp(int a, int b){ 2 return a -b; 3} 4 5int char_cmp(char a, char b){ 6 return int(a -b); 7}

こんな関数がいくつかあり、ソートする配列の型によって、読み込む関数ポインタを変えるものだと思っています。

実際に上記の2関数(int_cmp, char_cmp)を読み換えられるのでしょうか?
それとも何か根本的に間違っているのでしょうか?

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

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

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

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

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

guest

回答5

0

上記のようなconst void *型の引数を持つ関数ポインタにおいて

int func (int, int)を代入するにはどうすればいいんでしょうか?

キャストすれば良いのですが、関数の引数はポインタのはずで、それにintで受け取っても正常動作はしないでしょう。つまり、func関数の中身の処理の書き誤り。
sort_pointers関数の仕様を理解していないのでは?

void **arのような二重の値参照にはどんな意味なのですか?

単に二重なだけです。
何かの値を指すポインタへのポインタ。
三重なら、何かの値を指すポインタへのポインタへのポインタ。

投稿2019/07/03 16:53

otn

総合スコア84553

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

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

0

ベストアンサー

なんかtemplate関数なのにわざわざstd::function使う例を載せていらっしゃる人がいるのですが、最適化を阻害するだけでメリットがありませんのでやめましょう。やるならこうですね(C++17)

cpp

1template< 2 typename T, typename Comp, 3 std::enable_if_t<std::is_invocable_r_v<int, Comp, int, int>, std::nullptr_t> = nullpter 4> 5void sort(T* t, std::size_t n, Comp&& comp) 6{ 7 //do something 8}

C++20ではconceptが入ったのでもうちょっと読みやすく書けるとは思いますがここでは書きません。

というか関数ポインタの扱いについて聞きたい質問であって関数っぽいものを渡せれば手段は問わないという話では無かったはずでは・・・?

ref:


実際に上記の2関数(int_cmp, char_cmp)を読み換えられるのでしょうか?
それとも何か根本的に間違っているのでしょうか?

間違っています。普通この手の汎用的な関数ポインタを受け取る関数にわたす関数は

c

1int int_cmp(const void* a, const void* b){ 2 return *((const int*)(a)) - *((const int*)(b)); 3} 4 5int char_cmp(const void* a, const void* b){ 6 return *((const char*)(a)) - *((const char*)(b)); 7}

のようにします。ばらばらな関数型のポインタをむりやりキャストでねじ込むのはだめです。どうせstrict aliasing rulesに引っかかって未定義動作になってめでたく鼻から悪魔が召喚されます。

ref:

投稿2019/07/04 05:09

編集2019/07/04 05:10
yumetodo

総合スコア5850

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

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

0

sort_pointer だから、ポインタの配列をソートするんだと思います。
第1引数は、void * の配列の先頭アドレスでないといけません。
次のようにするしかないのでは?

C++

1#include <iostream> 2using namespace std; 3 4void sort_pointers(void **ar, int n, int(*cmp)(const void *, const void *)); 5 6int int_cmp(const void *a, const void *b) 7{ 8 return *(int *)a - *(int *)b; 9} 10 11int char_cmp(const void *a, const void *b) 12{ 13 return *(char *)a - *(char *)b; 14} 15 16int main() 17{ 18 int nums[4] = { 3, 1, 4, 2 }; 19 void *pnums[4]; 20 for (int i = 0; i < 4; i++) pnums[i] = &nums[i]; // ポインタ配列を作る 21 sort_pointers(pnums, 4, int_cmp); 22 for (int i = 0; i < 4; i++) cout << " " << *(int *)pnums[i]; 23 cout << "\n"; 24 25 char chars[] = "program"; 26 void *pchars[7]; 27 for (int i = 0; i < 7; i++) pchars[i] = &chars[i]; // ポインタ配列を作る 28 sort_pointers(pchars, 7, char_cmp); 29 for (int i = 0; i < 7; i++) cout << *(char *)pchars[i]; 30 cout << "\n"; 31} 32 33void sort_pointers (void **ar, int n, int(*cmp)(const void *, const void *)) 34{ 35 for (int i = 0; i < n-1; i++) { 36 for (int j = i + 1; j < n; j++) { 37 if (cmp(ar[i], ar[j]) > 0) { 38 void *t = ar[i]; 39 ar[i] = ar[j]; 40 ar[j] = t; 41 } 42 } 43 } 44}

投稿2019/07/04 01:47

kazuma-s

総合スコア8224

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

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

0

こんにちは。

C++でソートするなら、std::sortの使い方を悟りさえできれば、「お望みと思われるソート」も容易に可能です。

投稿2019/07/03 17:29

Chironian

総合スコア23272

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

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

0

void *はどんな「ポインタ型」であっても入れられます
しかし、int *は「ポインタ型」ですが、intは「ポインタ型」ではありません

void *はC言語時代の古い書き方なので、どちらかというと非推奨気味の書式であり、
C++の機能を使った書き方のほうが好まれます

sortの場合はこうですね

template<typename T> void sort(T *t, int num, std::function<int (const T &, const T &)> cmp);

投稿2019/07/04 02:52

izmktr

総合スコア2856

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問