のんびりしているエンジニアの日記

ソフトウェアなどのエンジニア的な何かを書きます。

constを付けた時は伝播に気をつけよう

Sponsored Links

皆さんこんにちは
お元気ですか。私は元気です。

さて、C++ templateで引っかかってしまって解決になぜか異常に時間がかかるような内容だったので、掲載します。

エラーメッセージは以下のような形式でした。

./UblasLibrary.hpp:116:10: error: no matching function for call to 'apply_function_to_element'
                return apply_function_to_element(ublas_class, fc);
                       ^~~~~~~~~~~~~~~~~~~~~~~~~
ActiveFunction.cpp:5:21: note: in instantiation of function template specialization 'ublas_func::sigmoid<boost::numeric::ublas::matrix<double,
      boost::numeric::ublas::basic_row_major<unsigned long, long>, boost::numeric::ublas::unbounded_array<double, std::__1::allocator<double> > > >' requested here
        return ublas_func::sigmoid(ublas_object);
                           ^
./UblasLibrary.hpp:121:54: note: candidate template ignored: could not match 'vector' against 'matrix'
        BOOST_UBLAS_INLINE boost::numeric::ublas::vector<T> apply_function_to_element(boost::numeric::ublas::vector<T> &ublas_vector,Function *fc){
                                                            ^
./UblasLibrary.hpp:132:54: note: candidate template ignored: substitution failure [with T = double]
        BOOST_UBLAS_INLINE boost::numeric::ublas::matrix<T> apply_function_to_element(boost::numeric::ublas::matrix<T> &ublas_matrix,Function *fc){

因みにコードの状況はこんな感じでした。

ublas::matrix<double> SigmoidFunction::execute(const ublas::matrix<double> &ublas_object){
	return ublas_func::sigmoid(ublas_object);
}

template<typename T>
T sigmoid(const T &ublas_class){
	Function *fc = new SigmoidFunction();
	return apply_function_to_element(ublas_class, fc);
}

/** vector全てに適用 */
template<typename T>
boost::numeric::ublas::vector<T> apply_function_to_element(boost::numeric::ublas::vector<T> &ublas_vector,Function *fc){
	int size = ublas_vector.size();
	boost::numeric::ublas::vector<T> result(size);
	for(int i = 0; i < size; i++){
		result[i] = fc->calc(ublas_vector[i]);
	}
	return result;
}

/** matrix全てに適用 */
template<typename T>
boost::numeric::ublas::matrix<T> apply_function_to_element(boost::numeric::ublas::matrix<T> &ublas_matrix,Function *fc){
	boost::numeric::ublas::matrix<double> result(ublas_matrix.size1(),ublas_matrix.size2());
	for(int i = 0; i < ublas_matrix.size1(); i++){
		for(int j = 0; j < ublas_matrix.size2(); j++){
			result(i,j) = fc->calc(ublas_matrix(i,j));
		}
	}
	return result;
}

さて、何がダメかわかりましたか?
原因は一つですが、templateのエラーは2つ検出されています。
一つはこちら

candidate template ignored: could not match 'vector' against 'matrix'

要は渡してるのvectorに対して、matrix型だとおっしゃっています。

candidate template ignored: substitution failure

代用に失敗したとか抜かしておりますが、何があったのでしょうか。結構困った結果なのですが、原因は単純です。

template<typename T>
T sigmoid(const T &ublas_class){

template<typename T>
boost::numeric::ublas::matrix<T> apply_function_to_element(boost::numeric::ublas::matrix<T> &ublas_matrix,Function *fc)

これだけ見ていれば実はバグの原因がわかります。

実はconstのつけ忘れです。つまり、正しくは

template<typename T>
boost::numeric::ublas::matrix<T> apply_function_to_element(const boost::numeric::ublas::matrix<T> &ublas_matrix,Function *fc)

まさか、これに数時間引っかかるとは…。