Atacante declarar uma função que usa enable_if: chamada ambígua
-
19-09-2019 - |
Pergunta
Eu tenho alguns problemas para a frente declarar uma função que usa boost::enable_if
: o seguinte pedaço de código me dá um erro do compilador:
// 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;
}
Ao compilar, eu recebo uma "chamada ambígua para foo" erro. De acordo com a definição de enable_if
, o 'tipo' typedef corresponde a void
quando a condição for verdadeira, assim, tanto quanto eu posso ver, as duas assinaturas de jogo foo
. Porque o compilador acha que eles são diferentes, e existe uma maneira correta de foo
declarar a frente (de preferência sem repetir a parte enable_if
)?
Solução
Este não é apenas um problema com enable_if. Você obtém o mesmo erro no Visual Studio e gcc com o seguinte código:
struct TypeVoid {
typedef void type;
};
template<typename T>
void f();
template<typename T>
typename T::type f() {
}
int main()
{
f<TypeVoid>();
return 0;
}
Eu acho que o principal problema é que o tipo de retorno (antes instanciação) é parte da assinatura de uma função de modelo. Há mais informações aqui .
No que diz respeito o seu código, se a declaração refere-se à definição, você deve combinar ambos:
// 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 a declaração refere-se a uma função diferente, o compilador nunca seria capaz de escolher o correto para int s, porque ambos são válidos. No entanto, você pode desativar o primeiro para int s usando 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)
{
}
Outras dicas
O problema é que a declaração ea definição não coincidem.
A solução é que a declaração deve conter a mesma assinatura exata, eo pouco a 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;
}
Este compila bem em VC2008.