检查MSVC2012中声明的成员函数

Checking declared member function in MSVC2012

本文关键字:成员 函数 声明 MSVC2012 检查      更新时间:2023-10-16

我编写了以下代码,它在GCC 4.7和MSVC 2013下按预期编译和工作,但在MSVC 2012下无法编译:

#include <iostream>
template<typename TClass>
struct IsLoadableHelper {
    template<typename T, T t> struct Helper {};
    struct Mixin1 {
        void Load(std::istream*);
    };
    struct MixedStruct1 : public Mixin1, public TClass {};
    // template<typename U>
    // static char f(Helper<void(TClass::*)(std::istream*), &TClass::Load>*);
    template<typename U>
    static long f(Helper<void(Mixin1::*)(std::istream*), &U::Load>*);
    template<typename U>
    static char f(...);
    enum { value = sizeof(f<MixedStruct1>(0)) == sizeof(char) };
};
struct Loadable
{
    void Load(std::istream*);
};

struct DerivedLoadable : Loadable
{};

struct NotLoadable
{
};

int main(void)
{
    std::cout << IsLoadableHelper<NotLoadable>::value << std::endl;
    std::cout << IsLoadableHelper<Loadable>::value << std::endl;
    std::cout << IsLoadableHelper<DerivedLoadable>::value << std::endl;
    return 0;
}
#include "stdafx.h"
#include <iostream>
template<typename TClass>
struct IsLoadableHelper {
    template<typename T, T t> struct Helper {};
    struct Mixin1 {
        void Load(std::istream*);
    };
    struct MixedStruct1 : public Mixin1, public TClass {};
    template<typename U>
    static long f(Helper<void(Mixin1::*)(std::istream*), &U::Load>*);
    template<typename U>
    static char f(...);
    enum { value = sizeof(f<MixedStruct1>(0)) == sizeof(char) };
};
struct Loadable
{
    void Load(std::istream*);
};

struct NotLoadable
{
};
int main(void)
{
    std::cout << IsLoadableHelper<NotLoadable>::value << std::endl;
    std::cout << IsLoadableHelper<Loadable>::value << std::endl;
    return 0;
}

在 MSVC 2012 下编译期间,它返回以下错误:

1>Source.cpp(22): error C3867: 'IsLoadableHelper<TClass>::Mixin1::Load': function call missing  argument list; use '&IsLoadableHelper<TClass>::Mixin1::Load' to create a pointer to member
1>          with
1>          [
1>              TClass=Loadable
1>          ]
1>          Source.cpp(43) : see reference to class template instantiation 'IsLoadableHelper<TClass>' being compiled
1>          with
1>          [
1>              TClass=Loadable
1>          ]
1>Source.cpp(22): error C3867: 'IsLoadableHelper<TClass>::Mixin1::Load': function call missing argument list; use '&IsLoadableHelper<TClass>::Mixin1::Load' to create a pointer to member
1>          with
1>          [
1>              TClass=DerivedLoadable
1>          ]
1>          Source.cpp(44) : see reference to class template instantiation  'IsLoadableHelper<TClass>' being compiled
1>          with
1>          [
1>              TClass=DerivedLoadable
1>          ]

我看到它无法解析指向 Load 函数的指针,并建议我获取指向基类的指针。这是意料之中的。但它报告了一个错误,而不是遵循 SFINAE 并继续,这是出乎意料的。我被限制只能使用 C++03,我需要使这段代码在 Visual Studio 2012 Update 4 下工作。如何修复?

更简单的替代方案怎么样:

template<typename TClass>
struct IsLoadableHelper {
    template<typename T, T> struct Helper;
    template<typename U>
    static long f(Helper<void (U::*)(std::istream*), &U::Load>*);
    template<typename U>
    static char f(...);
    enum { value = sizeof(f<TClass>(0)) == sizeof(char) };
};

这会满足MSVC2012吗?MSVC2013很开心!