Pergunta

Eu tenho bater em cima de um cérebro verdadeiro scorcher em C++, isso nunca aconteceu comigo antes.

A essência do problema é que, após a invocação de meu (modelo) função os argumentos que eu definiu padrões para ter seus valores mexidos.Isso só acontece se eu chamar a função com os padrões.

O meu modelo de função é declarada como este:

template <typename T>
vector2<T> transform(vector2<T> const &vec, matrix4<T> const &m, T z = T(0), T w = T(1));

É mais tarde, no mesmo cabeçalho, definido assim:

template <typename T>
inline vector2<T> transform(vector2<T> const &vec, matrix4<T> const &m, T z, T w)
{
 vector4<T> res = m * vector4<T>(vec.x, vec.y, z, w);
 return vector2<T>(res.x, res.y);
}

Agora, quando eu chamo isso com padrões (transform(vector2<double>(0, 1), view_transform)) Eu não obter os valores que eu esperava.Pisando em transform com o VC++s depurador eu ver z e w tendo "engraçado" valores " (que, na minha experiência significa que algo não está inicializado correctamente).

Exemplo engraçado valores seriam:0.0078125000000000000 e 2.104431116947 e-317#DEN

Agora eu tentei encontrar a resposta sobre C++ FAQ Lite, pesquisando-lo;até tentei me acalmar com Schubert, mas eu não posso para a vida de me descobrir.Eu estou supondo que é muito simples e eu suspeito que é algum tipo de modelo tomfoolery no trabalho.

Existe uma maneira de obter os valores padrão que eu espera e deseja, e por que ele faz isso comigo?

Edit 1:

Se eu a alteração de chamada e por isso usa flutua em vez (transform(vector2<float>(0, 1), view_transform)) o problema desaparece.Parece que este só ocorre se T = double.

Edit 2:

Isso só acontece se eu tenho duas especializações para double e float.Se eu usar uma bóia de especialização em um lugar, o casal de especialização se torna estranho valores padrão.Se eu alterar todos os lugares que a função é chamada, portanto, ele usa duas vezes a problemas de "vai embora".Eu ainda não entendo por que, parece que ele está usando com defeito deslocamentos ou algo assim, quando a configuração do z e w.

Edit 3:

Tales from the C++ Cripta:

#include <sgt/matrix4.hpp>

int main(int argc, char *argv[])
{
    sgt::matrix4<double> m0(
        2, 0, 0, 1,
        0, 2, 0, 1,
        0, 0, 1, 0,
        0, 0, 0, 1);

    m0 *= m0;

    sgt::vector2<double> blah0 = sgt::transform(sgt::vector2<double>(1, 0), m0);

    sgt::matrix4<float> m1(
        2, 0, 0, 1,
        0, 2, 0, 1,
        0, 0, 1, 0,
        0, 0, 0, 1);

    m1 *= m1;

    sgt::vector2<float> blah1 = sgt::transform(sgt::vector2<float>(1, 0), m1);

    printf("%f", blah0.x);
    printf("%f", blah1.x);
}

Em matrix4.hpp:

// ...

template <typename T>
vector2<T> transform(vector2<T> const &vec, matrix4<T> const &m, T z = T(0), T w = T(1));

template <typename T>
inline vector2<T> transform(vector2<T> const &vec, matrix4<T> const &m, T z, T w)
{
    vector4<T> res = m * vector4<T>(vec.x, vec.y, z, w);
    return vector2<T>(res.x, res.y);
}

// ...

Se eu executar o que, o duplo-especialização tem argumentos padrão correto, mas a flutuar versão obtém os argumentos padrão como zero (0.000000), que apesar de melhor, ainda não é z = 0 e w = 1.

Edit 4:

Fez um Ligue problema.

Foi útil?

Solução

A seguinte falha minha no Dev Studio:

#include "stdafx.h"
#include <vector>
#include <iostream>

template <typename T>
std::vector<std::vector<T> > transform(std::vector<std::vector<T> > const &vec,
                                       std::vector<std::vector<std::vector<std::vector<T> > > > const &m,
                                       T z = T(0), T w = T(1));


template <typename T>
std::vector<std::vector<T> > transform(std::vector<std::vector<T> > const &vec,
                                       std::vector<std::vector<std::vector<std::vector<T> > > > const &m,
                                       T z, T w)
{
    std::cout << "Z" << z << "\n";
    std::cout << "W" << w << "\n";

    return vec;
}

int _tmain(int argc, _TCHAR* argv[])
{
    std::vector<std::vector<int> >  xi;
    std::vector<std::vector<std::vector<std::vector<int> > > > mi;
    transform(xi,mi);

    std::vector<std::vector<float> >    xf;
    std::vector<std::vector<std::vector<std::vector<float> > > > mf;
    transform(xf,mf);

    std::vector<std::vector<double> >   xd;
    std::vector<std::vector<std::vector<std::vector<double> > > > md;
    transform(xd,md);
}

Saída:

Z0
W1
Z0
W1.4013e-045
Z2.122e-314
W3.60689e-305

Então eu suponho que ele não funcionar conforme o esperado!!!

Se você remover a pré-declaração e o padrão argumentos na função de modelo, então ele funciona como o esperado.

#include "stdafx.h"
#include <vector>
#include <iostream>

template <typename T>
std::vector<std::vector<T> > transform(std::vector<std::vector<T> > const &vec,
                                       std::vector<std::vector<std::vector<std::vector<T> > > > const &m
                                       T z = T(0), T w = T(1))
{
    std::cout << "Z" << z << "\n";
    std::cout << "W" << w << "\n";

    return vec;
}

int _tmain(int argc, _TCHAR* argv[])
{
    std::vector<std::vector<int> >  xi;
    std::vector<std::vector<std::vector<std::vector<int> > > > mi;
    transform(xi,mi);

    std::vector<std::vector<float> >    xf;
    std::vector<std::vector<std::vector<std::vector<float> > > > mf;
    transform(xf,mf);

    std::vector<std::vector<double> >   xd;
    std::vector<std::vector<std::vector<std::vector<double> > > > md;
    transform(xd,md);
}

Isso funciona como esperado.
Isso tem algo a ver com o modelo pré-declaração, na verdade, não sendo uma função pré-declaração e, assim, ele, na verdade, não tem padrão de parâmetros e, como tal, você está recebendo valores aleatórios na lista de parâmetros.

OK.Não de minha leitura da norma isso deve funcionar conforme o esperado:

Usando n2521
Seção 14.7.1 instância Implícita
Parágrafo 9

Uma implementação não deve implicitamente instanciar um modelo de função, um modelo de membro, uma não-função de membro virtual, um membro de classe ou membro de dados estáticos de uma classe de modelo que não necessitam de instanciação.Ele não é especificado se é ou não uma implementação implicitamente instancia uma função de membro virtual de um modelo de classe, se a função de membro virtual não ser instanciado.O uso de um modelo de especialização, em um argumento padrão não deve provocar o modelo implicitamente ser instanciado, exceto que um modelo de classe pode ser instanciado, onde o seu tipo completa é necessária para determinar a correção do padrão de argumento. O uso de um padrão de argumento em uma chamada de função faz com especializações no argumento padrão implicitamente ser instanciado.

O negrito parte do parágrafo parece (para mim) para indicar que cada especialização criado por causa do padrão argumentos serão implicitamente instanciado na unidade de tradução, quando utilizado.

Parágrafo 11:

Se um modelo de função f é chamado de uma forma que exige um padrão de expressão de argumento para ser usado, o dependente nomes são olhou para cima, a semântica restrições são verificadas, e a instanciação de qualquer modelo usado no padrão de expressão de argumento é feito como se o padrão de expressão de argumento tinha sido uma expressão usada em uma especialização de modelo de função com o mesmo escopo, o mesmo modelo de parâmetros e o mesmo acesso que o modelo de função f utilizada no momento.Esta análise é chamada de padrão de argumento de instanciação.O instanciado o argumento padrão é, então, usado como argumento de f.

Indica que, mesmo se os argumentos padrão são parâmetros do modelo que será instanciado corretamente.

Bem, espero que eu interpretados corretamente.:-)

Outras dicas

É o código otimizado?Talvez por isso o depurador está mostrando a você os valores errados.

Eu tentei este código mais simples (em g++ 4.3.3) e funciona como esperado.

template <typename T>
T increment(T a, T b = T(1))
{
    return a + b;
}

int main()
{
    double a = 5.0;
    std::cout << increment(a) << ", ";
    std::cout << increment(a, 3.0) << "\n";
}

Eu não sei se isso vai funcionar, mas tente usar um static_cast em vez de um " C " estilo de elenco para seus valores padrão.

*Editar: Aparentemente, o problema é que o compilador.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top