【问题标题】:OpenCL on Microsoft Visual Studio: templates cannot be declared to have C linkageMicrosoft Visual Studio 上的 OpenCL:不能将模板声明为具有 C 链接
【发布时间】:2018-04-10 00:22:17
【问题描述】:

我目前正在学习如何使用 OpenCL 进行编码,并决定运行一些示例代码。我已经下载了 Intel SDK、Microsoft Visual Studio 2017 和它的相关插件。

当我尝试运行程序时,从英特尔下载的 %iNTELOCLSDKROOT 依赖项中包含的“附加依赖项”文件之一出现问题。我在尝试构建解决方案时遇到的错误是模板不能声明为具有 C 链接 (C2894)。此错误完全位于一个名为 xtr1common 的文件中。我尝试将文件名从 host.cpp 更改为 host.c,这消除了 C2894 错误,但随后出现了有关语法的新错误,因为它显然不是用 C 编写的。

有没有人遇到过这个问题,知道如何解决?我很困惑,因为我非常怀疑英特尔在他们的代码中存在错误,而且我很可能没有注意到其他一些问题。以防万一代码中可能有错误,我将其包含在下面。欢迎提出任何建议。

    // xtr1common internal header
#pragma once
#ifndef _XTR1COMMON_
#define _XTR1COMMON_
#ifndef RC_INVOKED
#include <yvals.h>

 #pragma pack(push,_CRT_PACKING)
 #pragma warning(push,_STL_WARNING_LEVEL)
 #pragma warning(disable: _STL_DISABLED_WARNINGS)
 #pragma push_macro("new")
 #undef new

_STD_BEGIN
    // STRUCT _Nil
struct _Nil
    {   // empty struct, for unused argument types
    };

    // TEMPLATE CLASS integral_constant
template<class _Ty,
    _Ty _Val>
    struct integral_constant
    {   // convenient template for integral constant types
    static constexpr _Ty value = _Val;

    using value_type = _Ty;
    using type = integral_constant;

    constexpr operator value_type() const _NOEXCEPT
        {   // return stored value
        return (value);
        }

    constexpr value_type operator()() const _NOEXCEPT
        {   // return stored value
        return (value);
        }
    };

    // ALIAS TEMPLATE bool_constant
template<bool _Val>
    using bool_constant = integral_constant<bool, _Val>;

using true_type = bool_constant<true>;
using false_type = bool_constant<false>;

    // TEMPLATE CLASS enable_if
template<bool _Test,
    class _Ty = void>
    struct enable_if
    {   // type is undefined for assumed !_Test
    };

template<class _Ty>
    struct enable_if<true, _Ty>
    {   // type is _Ty for _Test
    using type = _Ty;
    };

template<bool _Test,
    class _Ty = void>
    using enable_if_t = typename enable_if<_Test, _Ty>::type;

    // TEMPLATE CLASS conditional
template<bool _Test,
    class _Ty1,
    class _Ty2>
    struct conditional
    {   // type is _Ty2 for assumed !_Test
    using type = _Ty2;
    };

template<class _Ty1,
    class _Ty2>
    struct conditional<true, _Ty1, _Ty2>
    {   // type is _Ty1 for _Test
    using type = _Ty1;
    };

template<bool _Test,
    class _Ty1,
    class _Ty2>
    using conditional_t = typename conditional<_Test, _Ty1, _Ty2>::type;

    // TEMPLATE CLASS is_same
template<class _Ty1,
    class _Ty2>
    struct is_same
        : false_type
    {   // determine whether _Ty1 and _Ty2 are the same type
    };

template<class _Ty1>
    struct is_same<_Ty1, _Ty1>
        : true_type
    {   // determine whether _Ty1 and _Ty2 are the same type
    };

template<class _Ty,
    class _Uty>
    constexpr bool is_same_v = is_same<_Ty, _Uty>::value;

    // TEMPLATE CLASS remove_const
template<class _Ty>
    struct remove_const
    {   // remove top level const qualifier
    using type = _Ty;
    };

template<class _Ty>
    struct remove_const<const _Ty>
    {   // remove top level const qualifier
    using type = _Ty;
    };

template<class _Ty>
    using remove_const_t = typename remove_const<_Ty>::type;

    // TEMPLATE CLASS remove_volatile
template<class _Ty>
    struct remove_volatile
    {   // remove top level volatile qualifier
    using type = _Ty;
    };

template<class _Ty>
    struct remove_volatile<volatile _Ty>
    {   // remove top level volatile qualifier
    using type = _Ty;
    };

template<class _Ty>
    using remove_volatile_t = typename remove_volatile<_Ty>::type;

    // TEMPLATE CLASS remove_cv
template<class _Ty>
    struct remove_cv
    {   // remove top level const and volatile qualifiers
    using type = _Ty;
    };

template<class _Ty>
    struct remove_cv<const _Ty>
    {   // remove top level const and volatile qualifiers
    using type = _Ty;
    };

template<class _Ty>
    struct remove_cv<volatile _Ty>
    {   // remove top level const and volatile qualifiers
    using type = _Ty;
    };

template<class _Ty>
    struct remove_cv<const volatile _Ty>
    {   // remove top level const and volatile qualifiers
    using type = _Ty;
    };

template<class _Ty>
    using remove_cv_t = typename remove_cv<_Ty>::type;

    // TEMPLATE CLASS _Is_integral
template<class _Ty>
    struct _Is_integral
        : false_type
    {   // determine whether _Ty is integral
    };

template<>
    struct _Is_integral<bool>
        : true_type
    {   // determine whether _Ty is integral
    };

template<>
    struct _Is_integral<char>
        : true_type
    {   // determine whether _Ty is integral
    };

template<>
    struct _Is_integral<unsigned char>
        : true_type
    {   // determine whether _Ty is integral
    };

template<>
    struct _Is_integral<signed char>
        : true_type
    {   // determine whether _Ty is integral
    };

 #ifdef _NATIVE_WCHAR_T_DEFINED
template<>
    struct _Is_integral<wchar_t>
        : true_type
    {   // determine whether _Ty is integral
    };
 #endif /* _NATIVE_WCHAR_T_DEFINED */

template<>
    struct _Is_integral<char16_t>
        : true_type
    {   // determine whether _Ty is integral
    };

template<>
    struct _Is_integral<char32_t>
        : true_type
    {   // determine whether _Ty is integral
    };

template<>
    struct _Is_integral<unsigned short>
        : true_type
    {   // determine whether _Ty is integral
    };

template<>
    struct _Is_integral<short>
        : true_type
    {   // determine whether _Ty is integral
    };

template<>
    struct _Is_integral<unsigned int>
        : true_type
    {   // determine whether _Ty is integral
    };

template<>
    struct _Is_integral<int>
        : true_type
    {   // determine whether _Ty is integral
    };

template<>
    struct _Is_integral<unsigned long>
        : true_type
    {   // determine whether _Ty is integral
    };

template<>
    struct _Is_integral<long>
        : true_type
    {   // determine whether _Ty is integral
    };

template<>
    struct _Is_integral<unsigned long long>
        : true_type
    {   // determine whether _Ty is integral
    };

template<>
    struct _Is_integral<long long>
        : true_type
    {   // determine whether _Ty is integral
    };

    // TEMPLATE CLASS is_integral
template<class _Ty>
    struct is_integral
        : _Is_integral<remove_cv_t<_Ty>>::type
    {   // determine whether _Ty is integral
    };

template<class _Ty>
    constexpr bool is_integral_v = is_integral<_Ty>::value;

    // TEMPLATE CLASS _Is_floating_point
template<class _Ty>
    struct _Is_floating_point
        : false_type
    {   // determine whether _Ty is floating point
    };

template<>
    struct _Is_floating_point<float>
        : true_type
    {   // determine whether _Ty is floating point
    };

template<>
    struct _Is_floating_point<double>
        : true_type
    {   // determine whether _Ty is floating point
    };

template<>
    struct _Is_floating_point<long double>
        : true_type
    {   // determine whether _Ty is floating point
    };

    // TEMPLATE CLASS is_floating_point
template<class _Ty>
    struct is_floating_point
        : _Is_floating_point<remove_cv_t<_Ty>>::type
    {   // determine whether _Ty is floating point
    };

template<class _Ty>
    constexpr bool is_floating_point_v = is_floating_point<_Ty>::value;

    // TEMPLATE CLASS is_arithmetic
template<class _Ty>
    struct is_arithmetic
        : bool_constant<is_integral<_Ty>::value
            || is_floating_point<_Ty>::value>
    {   // determine whether _Ty is an arithmetic type
    };

template<class _Ty>
    constexpr bool is_arithmetic_v = is_arithmetic<_Ty>::value;

    // TEMPLATE CLASS remove_reference
template<class _Ty>
    struct remove_reference
    {   // remove reference
    using type = _Ty;
    };

template<class _Ty>
    struct remove_reference<_Ty&>
    {   // remove reference
    using type = _Ty;
    };

template<class _Ty>
    struct remove_reference<_Ty&&>
    {   // remove rvalue reference
    using type = _Ty;
    };

template<class _Ty>
    using remove_reference_t = typename remove_reference<_Ty>::type;

_STD_END
 #pragma pop_macro("new")
 #pragma warning(pop)
 #pragma pack(pop)
#endif /* RC_INVOKED */
#endif /* _XTR1COMMON_ */

/*
 * Copyright (c) by P.J. Plauger. All rights reserved.
 * Consult your license regarding permissions and restrictions.
V6.50:0009 */

【问题讨论】:

  • 抱歉,我的意思是这些 错误 位于单个文件 xtr1common 中。总共有 52 个。
  • 问题不在此代码中,而在包含它的某个地方。你有没有extern "C" { #include &lt;something&gt; }?模板不能有 C 链接,因为 C 语言中没有模板。
  • 当我尝试在此处的英特尔示例页面中构建简单示例时收到上述错误消息 > software.intel.com/en-us/intel-opencl-support/code-samples。例如,我刚刚从缓冲区加载了示例 > Advanced OpenCL Samples for Windows Image。一旦我构建它,之前就会出现相同的消息......不能将模板声明为具有“c”链接。我查看了代码,没有看到像您所描述的那样。 :(

标签: c++ c visual-studio visual-studio-2015 opencl


【解决方案1】:

我发现这个头文件#includes xtr1common,并且在程序中有外部C。这可能是问题的根源吗?自从使用 SDK 从 Intel 下载后,我没有更改它。

    /* xtgmath.h internal header */

 #if defined(__cplusplus)
#pragma once
#ifndef _XTGMATH
#define _XTGMATH
#ifndef RC_INVOKED
#include <cstdlib>
#include <xtr1common>

 #pragma pack(push,_CRT_PACKING)
 #pragma warning(push,_STL_WARNING_LEVEL)
 #pragma warning(disable: _STL_DISABLED_WARNINGS)
 #pragma push_macro("new")
 #undef new

_STD_BEGIN
template<class _Ty1,
    class _Ty2>
    using _Common_float_type_t =
        conditional_t<is_same<_Ty1, long double>::value || is_same<_Ty2, long double>::value, long double,
        conditional_t<is_same<_Ty1, float>::value && is_same<_Ty2, float>::value, float,
        double>>;   // find type for two-argument math function
_STD_END

#define _CRTDEFAULT
#define _CRTSPECIAL _ACRTIMP

#define _GENERIC_MATH1R(FUN, RET, CRTTYPE) \
extern "C" _Check_return_ CRTTYPE RET __cdecl FUN(_In_ double); \
template<class _Ty, \
    class = _STD enable_if_t< _STD is_integral<_Ty>::value>> inline \
    RET FUN(_Ty _Left) \
    { \
    return (_CSTD FUN(static_cast<double>(_Left))); \
    }

#define _GENERIC_MATH1(FUN, CRTTYPE) \
    _GENERIC_MATH1R(FUN, double, CRTTYPE)

#define _GENERIC_MATH1X(FUN, ARG2, CRTTYPE) \
extern "C" _Check_return_ CRTTYPE double __cdecl FUN(_In_ double, ARG2); \
template<class _Ty, \
    class = _STD enable_if_t< _STD is_integral<_Ty>::value>> inline \
    double FUN(_Ty _Left, ARG2 _Arg2) \
    { \
    return (_CSTD FUN(static_cast<double>(_Left), _Arg2)); \
    }

#define _GENERIC_MATH2_CALL(FUN, CRTTYPE, CALL_OPT) \
extern "C" _Check_return_ CRTTYPE double CALL_OPT FUN(_In_ double, _In_ double); \
template<class _Ty1, \
    class _Ty2, \
    class = _STD enable_if_t< _STD is_arithmetic<_Ty1>::value && _STD is_arithmetic<_Ty2>::value>> inline \
    _STD _Common_float_type_t<_Ty1, _Ty2> FUN(_Ty1 _Left, _Ty2 _Right) \
    { \
    typedef _STD _Common_float_type_t<_Ty1, _Ty2> type; \
    return (_CSTD FUN(static_cast<type>(_Left), static_cast<type>(_Right))); \
    }

#define _GENERIC_MATH2(FUN, CRTTYPE) \
    _GENERIC_MATH2_CALL(FUN, CRTTYPE, __cdecl)

template<class _Ty1,
    class _Ty2,
    class = _STD enable_if_t< _STD is_arithmetic<_Ty1>::value && _STD is_arithmetic<_Ty2>::value>> inline
    _STD _Common_float_type_t<_Ty1, _Ty2> pow(const _Ty1 _Left, const _Ty2 _Right)
    {   // bring mixed types to a common type
    typedef _STD _Common_float_type_t<_Ty1, _Ty2> type;
    return (_CSTD pow(static_cast<type>(_Left), static_cast<type>(_Right)));
    }

//_GENERIC_MATH1(abs, _CRTDEFAULT)  // has integer overloads
_GENERIC_MATH1(acos, _CRTDEFAULT)
_GENERIC_MATH1(asin, _CRTDEFAULT)
_GENERIC_MATH1(atan, _CRTDEFAULT)
_GENERIC_MATH2(atan2, _CRTDEFAULT)
_GENERIC_MATH1(ceil, _CRTSPECIAL)
_GENERIC_MATH1(cos, _CRTDEFAULT)
_GENERIC_MATH1(cosh, _CRTDEFAULT)
_GENERIC_MATH1(exp, _CRTDEFAULT)

_GENERIC_MATH1(fabs, _CRT_JIT_INTRINSIC)

_GENERIC_MATH1(floor, _CRTSPECIAL)
_GENERIC_MATH2(fmod, _CRTDEFAULT)
_GENERIC_MATH1X(frexp, _Out_ int *, _CRTSPECIAL)
_GENERIC_MATH1X(ldexp, _In_ int, _CRTSPECIAL)
_GENERIC_MATH1(log, _CRTDEFAULT)
_GENERIC_MATH1(log10, _CRTDEFAULT)
//_GENERIC_MATH1(modf, _CRTDEFAULT)     // types must match
//_GENERIC_MATH2(pow, _CRTDEFAULT)  // hand crafted
_GENERIC_MATH1(sin, _CRTDEFAULT)
_GENERIC_MATH1(sinh, _CRTDEFAULT)
_GENERIC_MATH1(sqrt, _CRTDEFAULT)
_GENERIC_MATH1(tan, _CRTDEFAULT)
_GENERIC_MATH1(tanh, _CRTDEFAULT)

        // C99 MATH FUNCTIONS

        // TEMPLATE FUNCTION fma

inline float _Fma(float _Left, float _Middle, float _Right)
    {   // call float fma
    return (_CSTD fmaf(_Left, _Middle, _Right));
    }

inline double _Fma(double _Left, double _Middle, double _Right)
    {   // call double fma
    return (_CSTD fma(_Left, _Middle, _Right));
    }

inline long double _Fma(long double _Left, long double _Middle,
    long double _Right)
    {   // call long double fma
    return (_CSTD fmal(_Left, _Middle, _Right));
    }

template<class _Ty1,
    class _Ty2,
    class _Ty3> inline
    _STD _Common_float_type_t<_Ty1, _STD _Common_float_type_t<_Ty2, _Ty3>>
    fma(_Ty1 _Left, _Ty2 _Middle, _Ty3 _Right)
    {   // bring mixed types to a common type
    typedef _STD _Common_float_type_t<_Ty1, _STD _Common_float_type_t<_Ty2, _Ty3>> type;
    return (_Fma((type)_Left, (type)_Middle, (type)_Right));
    }

        // TEMPLATE FUNCTION remquo

inline float _Remquo(float _Left, float _Right, int *_Pquo)
    {   // call float remquo
    return (_CSTD remquof(_Left, _Right, _Pquo));
    }

inline double _Remquo(double _Left, double _Right, int *_Pquo)
    {   // call double remquo
    return (_CSTD remquo(_Left, _Right, _Pquo));
    }

inline long double _Remquo(long double _Left, long double _Right, int *_Pquo)
    {   // call long double remquo
    return (_CSTD remquol(_Left, _Right, _Pquo));
    }

template<class _Ty1,
    class _Ty2> inline
    _STD _Common_float_type_t<_Ty1, _Ty2>
    remquo(_Ty1 _Left, _Ty2 _Right, int *_Pquo)
    {   // bring mixed types to a common type
    typedef _STD _Common_float_type_t<_Ty1, _Ty2> type;
    return (_Remquo((type)_Left, (type)_Right, _Pquo));
    }

_GENERIC_MATH1(acosh, _CRTSPECIAL)
_GENERIC_MATH1(asinh, _CRTSPECIAL)
_GENERIC_MATH1(atanh, _CRTSPECIAL)
_GENERIC_MATH1(cbrt, _CRTSPECIAL)
_GENERIC_MATH2(copysign, _CRTSPECIAL)
_GENERIC_MATH1(erf, _CRTSPECIAL)
_GENERIC_MATH1(erfc, _CRTSPECIAL)
_GENERIC_MATH1(expm1, _CRTSPECIAL)
_GENERIC_MATH1(exp2, _CRTSPECIAL)
_GENERIC_MATH2(fdim, _CRTSPECIAL)
//_GENERIC_MATH3(fma, _CRTSPECIAL)  // hand crafted
_GENERIC_MATH2(fmax, _CRTSPECIAL)
_GENERIC_MATH2(fmin, _CRTSPECIAL)
_GENERIC_MATH2(hypot, _CRTSPECIAL)
_GENERIC_MATH1R(ilogb, int, _CRTSPECIAL)
_GENERIC_MATH1(lgamma, _CRTSPECIAL)
_GENERIC_MATH1R(llrint, long long, _CRTSPECIAL)
_GENERIC_MATH1R(llround, long long, _CRTSPECIAL)
_GENERIC_MATH1(log1p, _CRTSPECIAL)
_GENERIC_MATH1(log2, _CRTSPECIAL)
_GENERIC_MATH1(logb, _CRTSPECIAL)
_GENERIC_MATH1R(lrint, long, _CRTSPECIAL)
_GENERIC_MATH1R(lround, long, _CRTSPECIAL)
_GENERIC_MATH1(nearbyint, _CRTSPECIAL)
_GENERIC_MATH2(nextafter, _CRTSPECIAL)
_GENERIC_MATH1X(nexttoward, _In_ long double, _CRTSPECIAL)
_GENERIC_MATH2(remainder, _CRTSPECIAL)
//_GENERIC_MATH2X(remquo, _CRTSPECIAL)  // hand crafted
_GENERIC_MATH1(rint, _CRTSPECIAL)
_GENERIC_MATH1(round, _CRTSPECIAL)
_GENERIC_MATH1X(scalbln, _In_ long, _CRTSPECIAL)
_GENERIC_MATH1X(scalbn, _In_ int, _CRTSPECIAL)
_GENERIC_MATH1(tgamma, _CRTSPECIAL)
_GENERIC_MATH1(trunc, _CRTSPECIAL)

#undef _CRTDEFAULT
#undef _CRTSPECIAL
#undef _GENERIC_MATH1R
#undef _GENERIC_MATH1
#undef _GENERIC_MATH1X
#undef _GENERIC_MATH2_CALL
#undef _GENERIC_MATH2

 #pragma pop_macro("new")
 #pragma warning(pop)
 #pragma pack(pop)
#endif /* RC_INVOKED */
#endif /* _XTGMATH */
 #endif /* defined(__cplusplus) */

/*
 * Copyright (c) by P.J. Plauger. All rights reserved.
 * Consult your license regarding permissions and restrictions.
V6.50:0009 */

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-10-24
    • 1970-01-01
    • 2015-07-04
    • 1970-01-01
    • 2011-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多