1 つは特定のケースをキャッチし、もう 1 つは最初のケースと一致しない他のすべてのケースをキャッチするように、2 つのテンプレート関数を作成したいと考えています。std::enable_if を使用して特定のケースをキャッチしようとしていますが、コンパイラがあいまいな一致で失敗します。あいまいさがコンパイラによって解決されるように、これらのオーバーロードされた関数を作成するにはどうすればよいですか? (私はg ++を使用しています)
次のコードを書いてみました (これは問題を再現する簡単な例です)。
struct resource1_t{
};
struct resource2_t{
};
template <typename R, typename V>
struct unit_t{
typedef R resource_t;
typedef V value_t;
unit_t(value_t const& value):v(){}
value_t v;
value_t calcValue(resource_t const& r)const{return v;}
};
// Specific case (U::resource_t == R)
template <typename U, typename R, typename=std::enable_if_t<std::is_same_v<typename U::resource_t,R>>>
typename U::value_t callCalcValue(U const& u, R const& r){
return u.calcValue(r);
}
// General case (U::resource_t != R)
template <typename U, typename R>
typename U::value_t callCalcValue(U const& u, R const& r){
// Fail immediately!
assert(!"Unit resource does not match");
return U::value_t();
}
int main()
{
// Create an array of unit variants
typedef unit_t<resource1_t,int> U1;
typedef unit_t<resource2_t,float> U2;
std::vector<std::variant<U1,U2>> units;
units.emplace_back(U1(1));
units.emplace_back(U2(1.0f));
// Create a parallel array of resources
std::vector<std::variant<resource1_t,resource2_t>> resources;
resources.emplace_back(resource1_t());
resources.emplace_back(resource2_t());
// Call calcValue for each unit on the parallel resource
for(int i(0); i<units.size(); ++i){
std::visit([&](auto&& unit){
std::visit([&](auto&& resource){
// Fails to compile with substitution failure...
//std::cout << unit.calcValue(resource) << "\n";
// Results in ambiguous call compile error...
std::cout << callCalcValue(unit,resource) << "\n";
},resources[i]);
},units[i]);
}
}
私はコンパイラがすべてのケースを特定のケースに一致させ、他のすべての組み合わせを一般的なケースに一致させることを期待していましたstd::is_same_v<U::resource_t,R>
が、コンパイラは関数があいまいであると言って失敗しました。2番目の定義も試し! std::is_same
ましたが、コンパイラは失敗しますerror: redefinition of ... callCalcValue()...