dichiarando avanti una funzione che utilizza enable_if: chiamata ambigua
-
19-09-2019 - |
Domanda
Ho qualche problema in avanti dichiarando una funzione che utilizza boost::enable_if
: il seguente pezzo di codice mi dà un errore di compilazione:
// Declaration
template <typename T>
void foo(T t);
// Definition
template <typename T>
typename boost::enable_if<boost::is_same<T, int> >::type foo(T t)
{
}
int main()
{
foo(12);
return 0;
}
Quando si compila, ottengo un errore "chiamata ambigua alla foo". Secondo la definizione di enable_if
, il 'tipo' typedef corrisponde void
quando la condizione è vera, quindi, per quanto posso vedere, le due firme di partita foo
. Perché il compilatore pensa sono diversi, e c'è un modo corretto per inoltrare dichiarare foo
(preferibilmente senza ripetere la parte enable_if
)?
Soluzione
Questo non è solo un problema con enable_if. È possibile ottenere lo stesso errore su Visual Studio e gcc con il seguente codice:
struct TypeVoid {
typedef void type;
};
template<typename T>
void f();
template<typename T>
typename T::type f() {
}
int main()
{
f<TypeVoid>();
return 0;
}
Credo che il problema principale è che il tipo di ritorno (prima esemplificazione) fa parte della firma di una funzione template. Ci sono più informazioni qui .
Per quanto riguarda il codice, se la dichiarazione si riferisce alla definizione, si dovrebbe abbinare entrambi:
// Declaration
template <typename T>
typename boost::enable_if<boost::is_same<T, int> >::type foo(T t);
// Definition
template <typename T>
typename boost::enable_if<boost::is_same<T, int> >::type foo(T t)
{
}
Se la dichiarazione si riferisce ad una funzione diversa, il compilatore non sarebbe mai in grado di scegliere quello corretto per int s, perché entrambi sono validi. Tuttavia, è possibile disattivare il primo per int s utilizzando disable_if :
// Other function declaration
template <typename T>
typename boost::disable_if<boost::is_same<T, int> >::type foo(T t);
// Defition
template <typename T>
typename boost::enable_if<boost::is_same<T, int> >::type foo(T t)
{
}
Altri suggerimenti
Il problema è che la dichiarazione e la definizione non corrispondono.
La soluzione è che la dichiarazione deve contenere l'esatto firma stessa, e il bit del enable_if
.
#include <boost/type_traits/is_same.hpp>
#include <boost/utility/enable_if.hpp>
// Declaration
template <typename T>
typename boost::enable_if<boost::is_same<T, int> >::type foo(T t);
// Definition
template <typename T>
typename boost::enable_if<boost::is_same<T, int> >::type foo(T t)
{
}
int main()
{
foo(12);
return 0;
}
Questa compila bene su VC2008.