【问题标题】:error C2664 + generic classes + /Wp64错误 C2664 + 泛型类 + /Wp64
【发布时间】:2009-11-14 18:16:51
【问题描述】:

我有以下几行代码:

p_diffuse = ShaderProperty<Vector4>(Vector4(1,1,1,1));
addProperty(&p_diffuse, "diffuse");

p_shininess = ShaderProperty<float>(10.0f);
addProperty(&p_shininess, "shininess");

addProperty函数实现如下:

template <class A_Type> 
void IShader<A_Type>::addProperty( ShaderProperty<A_Type>* shaderProperty, 
                                   std::string propertyName )
{
  m_shaderProperties[propertyName] = shaderProperty;
}

现在我在第一块代码的最后一行得到一个奇怪的编译器错误。 addProperty 在第一种情况下工作正常,但在第二种情况下(尝试添加 p_shininess)我得到:

error C2664: 'IShader<A_Type>::addProperty': cannot convert parameter 1 from 'ShaderProperty<A_Type> *' to 'ShaderProperty<A_Type> *'

咦!? 问题的提示可能如下:如果我转到项目设置并在 C++ 常规选项卡中将“检查 64 位兼容性问题”从“否”设置为“是(/Wp64)”,则错误读数略显不同:

error C2664: 'IShader<A_Type>::addProperty': cannot convert parameter 1 from 'ShaderProperty<A_Type> *__w64 ' to 'ShaderProperty<A_Type> *'

怎么了?? __w64 是什么??

编辑:ISShader 的类定义:

template <class A_Type> class IShader {

public:
virtual ~IShader(void) {};
virtual A_Type shade(IntersectionData* iData, Scene* scene) = 0;

protected:

ShaderProperty<A_Type>* getProperty(std::string propertyName);
void addProperty(ShaderProperty<A_Type>* shaderProperty, std::string propertyName);

private:
std::map<std::string, ShaderProperty<A_Type>*> m_shaderProperties;
};

【问题讨论】:

    标签: c++ generics floating-point compiler-errors


    【解决方案1】:

    浮动!= Vector4。您的整个类(IShader)都在 A_Type 上进行模板化,而不仅仅是 addProperty 方法。 /Wp64 与任何事情无关。此问题的解决方案将需要更多上下文,您可能希望将 addProperty 定义为模板成员函数,而不是 IShader(或除此之外)被模板化。

    再一次,如果不确切知道您在做什么,这将很难做到,但我怀疑您想要的是一个异构的属性集合。要安全地执行此操作,您需要使用一些运行时检查。

     class ISharderProperty {
        public:
        virtual ~IProperty() {}
     };
    
     template<typename ShadeType>
     class IShader;
    
     template <typename T>
     class ShaderProperty : public IShaderProperty {
        IShader<T> *m_shader;
        ...
      };
    
     template<typename ShadeType>
     class IShader { 
        ShadeType shade(...) = 0;
        protected:
          map<string, IShaderProperty*> m_shaderProperties;
          template<typename T>
          void addProperty(ShaderProperty<T>* prop, string name) {
             m_shaderProperties[name] = prop;
          }
          template<typename T>
          void getProperty(const string& name, ShaderProperty<T>** outProp) {
             map<string, IShaderProperty*>::iterator i = m_shaderProperties.find(name);
             *outProp = NULL;
             if( i != m_shaderProperties.end() ) {
                 *outProp = dynamic_cast<ShaderProperty<T>*>( *i );
             }
          }
     };
    

    你必须使用 getProperty 之类的

    ShaderProperty<float> *x;
    ashader.getProperty("floatprop", &x);
    if( x ) {
        ...
    }
    

    或者,getProperty 可以直接返回值,但是你需要提到 T 两次,例如

    ShaderProperty<float> *x = ashader.getProperty<float>("floatprop");
    
    if( x ) { ... }
    

    您会注意到我使用dynamic_cast 并检查NULL。如果您有其他机制将属性名称映射到属性类型,您可以使用它和static_castdynamic_cast 有一些运行时开销。

    【讨论】:

    • 啊,看来你是对的.. 但是我该如何定义 addProperty 函数呢?我在问题描述中添加了 IShader 类的定义。 addProperty 应该允许将任何通用类型的属性添加到 m_shaderProperties 映射
    • 再次感谢!但是 IShader 也需要是通用的,因为它有一个需要返回通用值的“阴影”函数(可能有返回浮点数的着色器实例,其他返回 Vector4 等等)。每个着色器都应维护一个异构的属性集合(正如您正确假设的那样)。另一方面,每个属性都可以存储指向它自己的通用类型的着色器的指针(因此 - 着色器存储任意属性 - 属性存储它自己类型的着色器)。这也给了我相互包含的问题,需要以某种方式使用前向声明......
    • 查看我的最新文章,了解如何使 IShader 模板化并转发 decalre,以便 ShaderProperty 可以继续指向一个。
    • 像魅力一样工作! :) 非常感谢你!!剩下的唯一问题是我看不到如何将定义与实现分开。在 cpp 文件中编写 getProperty() 的实现的正确语法是什么?
    • 假设您了解限制(即您知道您实际上不能使用模板进行单独编译),语法看起来像 template&lt;typename ShaderType&gt; template&lt;typename T&gt; void IShader&lt;ShaderType&gt;::getProperty(string, ShaderProperty&lt;T&gt;** out) { ... }
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-28
    • 2014-06-21
    • 2018-05-01
    相关资源
    最近更新 更多