VC ++ 14模板指向成员和指向成员函数的指针之间存在歧义

时间:2015-12-14 21:21:37

标签: c++ c++14

我使用vs14编译器的函数模板有问题。 所以下面的代码演示了这个问题。

#include <iostream>
using namespace std;

class Class {
public:
    int memberFoo() {
        return 0;
    }
};

template <class VariableT, class C>
void nothing(const VariableT C::*memberV) {
    cout << "Pointer to member variable";
}

template <class R, class C>
void nothing(R (C::*memberF)()) {
    cout << "Pointer to member function";
}

int main() {

    nothing(&Class::memberFoo);

    return 0;
}

编译器让我知道nothing函数含糊不清。当我看到输出时,它似乎有其他行为超出我的预期。 在第一个nothing函数中,编译器将VariableT推导为int(void)。实际上并不奇怪,但我认为第二个更合适并且会匹配。更有意思的是,如果在第一个重载函数中删除const,程序将正确编译。 你能建议我怎么处理这个吗?

1 个答案:

答案 0 :(得分:6)

您可以使用一些方便的type_traits is_member_function_pointeris_member_object_pointer来修复它:

template <class R, class C>
void nothing(R (C::*memberF)())
{
    std::cout << "Pointer to function" << std::endl;
}

template <class VariableT, class C>
auto nothing(const VariableT C::* memberV)-> typename std::enable_if<std::is_member_object_pointer<decltype(memberV)>::value>::type
{
    cout << "Pointer to member variable";
}

Live Demo

std::enable_if的默认类型为void,因此返回类型仍为void

从你的帖子看起来听起来应该实例化成员函数模板,但是Visual Studio和Clang都对模糊性大喊大叫,我认为这是公平的,给定Type Class::*,你可以推断出一个指向成员或指针的指针成员函数,假设ReturnType()的替换对Type有效(这是我们正在看到的)。

所以我决定跳过所有这些并利用尾随返回类型直接询问参数。

修改

link

中加入T.C.'s comment中的文字
  

章节:14.8.2.1 [temp.deduct.call]
  目前尚不清楚以下是否形成良好:

void foo(){}

template<class T>
void deduce(const T*) { }

int main() {
  deduce(foo);
}
     

实施方案对此示例的处理方式各不相同。

确实,您注意到删除const也消除了歧义。