C言語のエラー C2672:原因と対処法について解説
Visual Studioなどの開発環境でC言語のプログラムを作成する際に、エラー C2672 が表示される場合があります。
このエラーは、呼び出そうとする関数に合致するオーバーロードが存在しないことが原因です。
まずは、渡している引数の型や定義を見直していただくと解決に近づくかもしれません。
エラー C2672 の概要
エラー C2672 は、関数呼び出し時に呼び出し先のオーバーロード関数が見つからず、適切な一致が得られなかった場合に発生するエラーです。
エラーメッセージでは「No matching overloaded function found」と表示され、関数のオーバーロードや引数の型、アクセシビリティに関する問題が考えられます。
エラー発生の背景
このエラーは、関数呼び出し時にコンパイラが適切なオーバーロードを解決できなかった場合に発生します。
具体的には、
- 呼び出される関数の引数の型が定義側と一致しない場合
- 関数が複数定義されている状況で、どの関数を選べばよいのか判断できない場合
- オーバーロード解決時に、関数のアクセシビリティ(public/privateなど)の制約により、適用可能な関数が存在しない場合
のような状況が考えられます。
特に、テンプレートやSFINAE(Substitution Failure Is Not An Error)の仕組みが絡むと、名前空間や型のアクセスに関する問題が顕在化しやすくなります。
発生条件と注意点
エラー C2672 が発生する主な条件は次の通りです。
- 関数呼び出し時に引数の型が一致していない場合
- 定義側が非公開メンバーやフレンド関数など、アクセス制限された箇所にある場合
- テンプレート内でのコンパイル時評価において、型情報が正しく解釈されなかった場合
また、開発中は以下の点に注意することが求められます。
- 関数のオーバーロード定義が複数ある場合、各オーバーロード間の引数型と順序が明確であることを確認する。
- コンパイラのバージョンや設定により、オーバーロード解決の挙動が異なる可能性があるため、開発環境に合わせた確認が必要となる。
原因の詳細解説
コンパイラがエラー C2672 を報告する際、主な原因は関数オーバーロードの不一致と、定義側と呼び出し側の矛盾の2点に集約されます。
関数オーバーロードによる不一致
型一致の確認不足
関数オーバーロードの際には、渡された引数の型と定義側の引数型が一致している必要があります。
たとえば、関数が引数として int
型を期待しているのに対し、double
型を渡した場合、暗黙の型変換が行われない状況では一致と認識されず、エラーが発生します。
また、テンプレート関数などでは、型の推論が正確に行われない場合にも同様の不一致が原因となることがあります。
呼び出し時の誤った引数指定
関数呼び出しで、順序が異なる引数や数が合わない引数を渡してしまった場合もエラーの原因となります。
この場合、意図したオーバーロード関数が呼び出せず、コンパイラが適切なオーバーロードを選択できない状況が発生します。
定義側と呼び出し側の矛盾
アクセシビリティの問題
関数が定義されている側でのアクセス指定(たとえば private
や protected
)と、呼び出し側の要求との間に矛盾がある場合、コンパイラは一致する関数を見つけられずにエラー C2672 を提示します。
この問題は、特にクラスのメンバー関数を呼び出す際や、テンプレート関数内でフレンド関数へのアクセスを試みる際に起こりやすく、定義側でのアクセス指定と呼び出し側のコンテキストの違いに注意が必要です。
対処法の検証
関数定義の見直し
引数型の調整方法
引数の型や数に問題がある場合は、関数の定義と呼び出し時に指定する型を一致させる必要があります。
例えば、以下のような状況を考えます。
- 関数が
int
型の引数を期待しているのに対し、呼び出し側でlong
型やdouble
型が渡されている場合、意図した型変換が行われるか、もしくは明示的に型キャストを行う必要があります。 - テンプレート関数の場合、型推論が正しく行われているか確認し、必要に応じてテンプレート引数を明示することが有効です。
定義の修正例
たとえば、以下はエラーが発生するコード例です。
#include <iostream>
// サンプル: 型情報を持つテンプレートクラス
template <class T>
class Sample {
// アクセス指定がコメントアウトされているため非公開になっている場合、アクセスエラーが発生する
// public: // この行のコメントアウトを解除することでアクセス可能になる
typedef T Type;
};
// サンプル関数: 型が整数型の場合にのみ適用
template <class T, typename std::enable_if<std::is_integral<typename Sample<T>::Type>::value, int>::type = 0>
bool isZero(T x) {
return (x == 0);
}
int main() {
// 関数呼び出し時にSampleの型が非公開のため、エラー C2672 が発生する可能性がある
std::cout << "10 はゼロか? " << (isZero(10) ? "はい" : "いいえ") << std::endl;
return 0;
}
10 はゼロか? いいえ
上記の例では、typedef
の位置やアクセス指定が原因で、正しい型推論が行われずエラーが発生する場合があります。
必要に応じてアクセス指定を修正し、呼び出し側と定義側の整合性を確保することが重要です。
コンパイラ設定の確認
開発環境ごとの注意事項
コンパイラのバージョンや設定、あるいは標準ライブラリの実装によって、オーバーロード解決やテンプレートの動作が異なる場合があります。
たとえば、Visual Studio 2017 以降のバージョンでは、以前のバージョンと比較してコンパイラによるアクセス確認が厳格になっているため、同じコードでもエラー C2672 を引き起こす可能性があります。
以下の点を確認することが役立ちます。
- コンパイラのバージョンに合わせたコードの記述
- テンプレートやオーバーロード関数の実装方法が、最新の標準に適合しているか確認する
- コンパイラの警告やエラーメッセージを詳細に確認し、どの部分が原因でエラーとなっているか精査する
コード例による検証
エラー発生コードの分析
再現サンプルコードの検討
次のサンプルコードは、アクセス指定の誤りが原因でエラー C2672 を引き起こす例です。
#include <iostream>
#include <type_traits>
// 型情報を持つテンプレートクラス
template <class T>
class MyType {
// public キーワードがないため、デフォルトで非公開となる
typedef T Type;
};
// テンプレート関数: 整数型の場合にのみ適用する関数
template <class T, typename std::enable_if<std::is_integral<typename MyType<T>::Type>::value, int>::type = 0>
bool checkZero(T x) {
return (x == 0);
}
int main() {
// 関数呼び出しでエラー C2672 が発生する可能性がある部分
std::cout << "値 10 はゼロか? " << (checkZero(10) ? "はい" : "いいえ") << std::endl;
return 0;
}
コンパイルエラー: Error C2672 によりオーバーロード関数が見つかりません
この例では、テンプレートクラス MyType
内の typedef
が非公開となっており、テンプレート関数内でアクセスできないため、オーバーロード解決に失敗します。
修正後のコード例
修正ポイントの詳細説明
修正後は、typedef
を公開することで、テンプレート関数が正常に型情報へアクセスできるように変更します。
#include <iostream>
#include <type_traits>
// 型情報を持つテンプレートクラス
template <class T>
class MyType {
public: // アクセス指定を public に変更
typedef T Type;
};
// テンプレート関数: 整数型の場合にのみ適用する関数
template <class T, typename std::enable_if<std::is_integral<typename MyType<T>::Type>::value, int>::type = 0>
bool checkZero(T x) {
return (x == 0);
}
int main() {
// 修正後は正しくコンパイルされ、実行結果が表示される
std::cout << "値 10 はゼロか? " << (checkZero(10) ? "はい" : "いいえ") << std::endl;
return 0;
}
値 10 はゼロか? いいえ
この修正例では、MyType
クラス内の型定義を public
節に移動することで、テンプレート関数が必要な型情報にアクセスできるようになり、エラー C2672 が解消されます。
まとめ
この記事では、C言語のエラー C2672 の発生背景や具体的な原因として、関数のオーバーロードの不一致、型一致の確認不足、呼び出し側と定義側の矛盾(特にアクセシビリティの問題)について解説しています。
また、引数型の調整や定義修正、コンパイラ設定の見直しといった対処法を、実行可能なサンプルコードを用いて分かりやすく示しています。