【问题标题】:Template instantiation with VARIANT return type具有 VARIANT 返回类型的模板实例化
【发布时间】:2009-01-08 19:38:33
【问题描述】:

静态模板成员函数的显式实例化始终无法编译并显示消息error C2785: 'at_Intermediate CUtil::convert_variant(const VARIANT &)' and '<Unknown>' have different return types

当我用非静态成员函数创建一个对应的类时,编译器喜欢我。

// utility class - static methods
struct CUtil {
      template< typename at_Intermediate > static at_Intermediate convert_variant( const VARIANT &v ) ;

      template<> static VARIANT convert_variant<VARIANT >( const VARIANT &v ) { return v; } // 
      template<> static double  convert_variant<double  >( const VARIANT &v ) { return v.dblVal; }
      template<> static long    convert_variant<long    >( const VARIANT &v ) { return v.lVal  ; }
      template<> static BSTR    convert_variant<BSTR    >( const VARIANT &v ) { return v.bstrVal; }
};

这是一个组合问题:

  1. 为什么编译器会抱怨一个函数“未知”,而它显然是已知的?

  2. 触发此消息的原因 - 当函数设为全局或非静态时它会消失。

编辑:

经过 Josh 的一些有用提示:是否不允许在类声明中显式实例化模板函数?

【问题讨论】:

    标签: c++ templates


    【解决方案1】:

    显然,您只能在命名空间范围内使用显式模板特化,尽管我在标准中找不到这一点(但 GCC 说了这么多)。以下对我有用(在 GCC 上):

    struct CUtil {
        template< typename at_Intermediate > static at_Intermediate convert_variant( const VARIANT &v ) ;
    };
    
    template<> VARIANT CUtil::convert_variant<VARIANT >( const VARIANT &v ) { return v; }
    template<> double  CUtil::convert_variant<double  >( const VARIANT &v ) { return v.dblVal; }
    template<> long    CUtil::convert_variant<long    >( const VARIANT &v ) { return v.lVal  ; }
    template<> BSTR    CUtil::convert_variant<BSTR    >( const VARIANT &v ) { return v.bstrVal; }
    

    EDIT在标准中:

    14.7.2.5:

    类或函数模板特化的显式实例化放置在定义模板的命名空间中。类模板成员的显式实例化放置在定义封闭类的命名空间中。 成员模板的显式实例被放置在定义封闭类或类模板的命名空间中。

    (我添加的所有重点。)

    【讨论】:

    • 这是一个明确的专业化,而不是实例化。 14.7.3p2:“显式特化应在模板所属的命名空间中声明,或者,对于成员模板,应在封闭类或封闭类模板所属的命名空间中声明。”适合你的情况:)
    • 啊 nvm,我只是看到它也是 OP 使用的,这不是你的错 :) 但也许你可以纠正他?
    • 这是OriginalPoster,这个人发布了这个问题。我想你知道两者之间的区别是什么,但万一不是:显式实例化会在当前翻译单元中为给定类型实例化模板(因此客户可以在其他地方使用模板而无需...
    • ...模板代码。显式特化为不同的类型放置不同的代码。 (在您的代码中,不同之处在于您在每个专业化中返回不同的成员)。
    • @litb:在我的理解中,显式特化实际上也实例化。不过,我可能是错的。特别是考虑到实例化有单独的语法。
    【解决方案2】:

    试试这个方法:

    struct CUtil {
        template< typename T > 
        static T convert_variant(const VARIANT &);
    };
    
    template<> int CUtil::convert_variant<int>(const VARIANT &);
    template<> VARIANT CUtil::convert_variant<VARIANT>(const VARIANT &);
    

    您不能在类范围内显式特化模板。 See here.

    VS2008 的一个奇怪问题是它确实有效。

    struct CUtil {
        template< typename T > 
        static T convert_variant(const VARIANT &);
        template<> 
        static int convert_variant<int>(const VARIANT &);
    };
    

    还有这个:

    struct CUtil {
        template< typename T > static void convert_variant(T);
        template<> static void convert_variant<VARIANT >(VARIANT);
    };
    

    【讨论】:

    • ...Comeau 还对类体内的显式实例化做出反应...在外部定义函数会产生好的结果。
    • 在 Codepad.org:相同的结果(非命名空间范围“struct CUtil”中的显式特化)
    • 你的第三个解决方案应该去掉'static'关键字(你没有在那里声明)
    • 顺便说一句 - 虽然你没有得到答案,但我为你的帖子 +1 了,因为它确实帮助我找到了问题。
    猜你喜欢
    • 2018-06-02
    • 2014-12-11
    • 2022-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多