我对SFINAE有疑问,我遇到了一个意外的编译错误:) 这是我的代码: sfinae.h:
#include <iostream>
#include <type_traits>
template <typename T>
struct RouteManager
{
template <typename ROUTER, typename u = void>
struct hasMethod : std::false_type
{
};
template <typename ROUTER>
struct hasMethod<ROUTER, decltype(&ROUTER::RouteAll, void())> : std::true_type
{
};
void f()
{
f(hasMethod<ORDER_ROUTER>{});
}
void f(std::false_type)
{
std::cout << "false type" << std::endl;
}
void f(std::true_type)
{
order_router.RouteAll();
std::cout << "true type" << std::endl;
}
using ORDER_ROUTER = typename T::ORDER_ROUTER;
ORDER_ROUTER order_router;
};
下面是sfinae.cpp:
#include "sfinae.h"
template <typename A>
struct RouterA
{
};
template <typename DERIVED>
struct Base{};
struct TestTypes : Base<TestTypes>
{
using ORDER_ROUTER = RouterA<TestTypes>;
};
template <typename B>
struct RouterB
{
void RouteAll(){std::cout << "cancelAll";}
};
template class RouteManager<TestTypes> ;
int main()
{
}
当我编译此代码时,错误出现并显示“错误:'使用ORDER_ROUTER =使用ORDER_ROUTER =结构RouterA {aka结构RouterA}'没有名为'RouteAll'的成员”“,我知道这是因为{{1 }},但不应该将它限制在f(std :: false_type)上吗?
答案 0 :(得分:1)
SFINAE仅适用于替换模板本身的模板参数。 f
是一个类模板的成员,它甚至不是模板本身,并且您试图替换其包围的类模板的template参数,因此没有SFINAE。
此外,非正式地,SFINAE仅出现在模板的签名中,而不出现在模板的定义中。
对于C ++ 17,您可以使用if constexpr
:
void f()
{
if constexpr (hasMethod<ORDER_ROUTER>{}) {
order_router.RouteAll();
std::cout << "true type" << std::endl;
}
else std::cout << "false type" << std::endl;
}