質問のコードの問題は、long
またはTemplateString
に変換可能な引数が渡された場合、テンプレートが最もよく一致することです。テンプレートは変換を行う必要はなく、他の関数を呼び出す際には変換が必要です。
std::enable_if
を使用しなくても目的の動作を達成できますが、std::enable_if
の使用は禁止されていると考えられますが、C++ 2011やBoostを使用できない場合でも非常に簡単ですstd::enable_if
を実装します。望ましい型の特性のいくつかを実装することは少し困難ですが実行可能です。その使用を効果的に制限するということは、本質的に同じ論理を実際に何を言わないように、多かれ少なかれ工夫して実装する必要があることを意味します。たとえば、このコードはstd::enable_if
またはSFINAEを使用しませんが、SFINAEが使用されていた場合に必要とされない、実際に作成され、余分なオブジェクトがある:
#include <iostream>
#include <string>
class SetProxy {
template <typename F>
struct helper {
helper(F const& v): value_(v) {}
F const& value_;
};
template<typename F>
void aux(helper<F> value, ...) {
std::cout << "template " << value.value_ << "\n";
}
template<typename F>
void aux(long value, int) {
std::cout << "long: " << value << "\n";
}
template<typename F>
void aux(std::string const& value, int) {
std::cout << "string: " << value << "\n";
}
public:
template<typename T>
void operator=(const T& value) {
this->aux<T>(value, 0);
}
};
struct foo {};
std::ostream& operator<< (std::ostream& out, foo const&) {
return out << "foo";
}
int main()
{
SetProxy p;
p = 17l;
p = 17;
p = foo();
p = "hello";
p = std::string("hello");
}
は、これは、元のタイプを使用していません私はそれらをアクセス可能にしていないので、私は実際の質問に関係のないものをタイプするように感じなかったので、質問。これには、std::is_convertible
の実装の重要なビットが効果的に含まれていることに注意してください。内部的には、代入演算子に可変引数リストを持たせることができないため、別のテンプレートに転送する必要があります。int
からhelper<int>
への実行可能な変換があるため、型を区別するその他のものがなければあいまいさがありますテンプレートのバージョンを少し悪くするために引数リストが使用されています。
class SetProxy {
public:
template <typename T>
typename std::enable_if<!std::is_convertible<T, long>::value
&& !std::is_convertible<T, std::string>::value, void>::type
operator= (T const& value) {
std::cout << "template: " << value << "\n";
}
void operator= (long value) {
std::cout << "long: " << value << "\n";
}
void operator= (std::string value) {
std::cout << "std::string: '" << value << "'\n";
}
};
なぜテンプレート以外のバージョンが必要ですか?なぜあなたはテンプレートを特化できないのですか? –
問題を再現できません。 –