我正试图做一些有趣的事情,但它在 VC++ 2015 上中断了.我在 clang 试过了和 g++并且没有编译或运行时错误。 (链接到 rextester.com 演示)
#include <type_traits>
#include <iostream>
int fn1() { return 1; }
int fn2(int) { return 2; }
template <typename FN_T, FN_T FN, typename DERIVED>
class test_base
{
template <typename T = DERIVED, typename = std::enable_if_t<!T::fn_specified>>
int fn()
{
return FN();
}
public:
int fn_indirect()
{
return static_cast<DERIVED*>(this)->fn();
}
};
template <typename FN_T, FN_T FN, typename ENABLER = void>
class test_derived : public test_base<FN_T, FN, test_derived<FN_T, FN>>
{
public:
static constexpr bool fn_specified = false;
};
template <typename FN_T, FN_T FN>
class test_derived<FN_T, FN, std::enable_if_t<FN == &fn2>>
: public test_base<FN_T, FN, test_derived<FN_T, FN>>
{
using base = test_base<FN_T, FN, test_derived<FN_T, FN>>;
friend base;
public:
static constexpr bool fn_specified = true;
int fn()
{
return FN(1);
}
};
int main(void)
{
test_derived<decltype(&fn1), &fn1> x1;
test_derived<decltype(&fn2), &fn2> x2;
std::cout << x1.fn_indirect() << " ";
// comment next line out and it'll work in VC++
std::cout << x2.fn_indirect() << std::endl;
return 0;
}
思路是,如果我在派生类中指定一个fn()
,那么基类就不会实例化该函数,这样调用时就不会因为参数过多而报错FN()
,当 FN()
指向特定函数时(在本例中为 fn2(int)
)。
我这样做是否正确,还是我遗漏了什么?
最佳答案
您使用的结构称为 Expression SFINAE。 Visual Studio 直到 2017 年才声明为 support it . Visual Studio 2015 的更新启用了部分支持(阅读更多关于 update 1 、 updates 1, 2 and 3 的信息)。然而,要使其在所有版本的 MSVC 中工作,需要创建不涉及表达式的变通方法,例如内部模板特化参数。要在您的情况下实现它,可以使用带有附加间接层的模式匹配(例如 std::integral_constant):
#include <type_traits>
#include <iostream>
int fn1() { return 1; }
int fn2(int) { return 2; }
template <typename FN_T, FN_T FN, typename DERIVED>
class test_base
{
template <typename T = DERIVED, typename = std::enable_if_t<!T::fn_specified>>
int fn()
{
return FN();
}
public:
int fn_indirect()
{
return static_cast<DERIVED*>(this)->fn();
}
};
template <class FN_T>
class test_derived : public test_base<typename FN_T::value_type, FN_T::value, test_derived<FN_T>>
{
public:
static constexpr bool fn_specified = false;
};
template <typename FN_T>
class test_derived<std::integral_constant<FN_T, &fn2>>
: public test_base<FN_T, &fn2, test_derived<std::integral_constant<FN_T, &fn2>>>
{
using base = test_base<FN_T, &fn2, test_derived<std::integral_constant<FN_T, &fn2>>>;
friend base;
public:
static constexpr bool fn_specified = true;
int fn()
{
return fn2(1);
}
};
int main(void)
{
test_derived<std::integral_constant<decltype(&fn1), &fn1>> x1;
test_derived<std::integral_constant<decltype(&fn2), &fn2>> x2;
std::cout << x1.fn_indirect() << " ";
// comment next line out and it will work
std::cout << x2.fn_indirect() << std::endl;
return 0;
}
关于c++ - 我是否正确地排除了 base 的 fn() 函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44599692/