进行SFINAE练习时编译错误

时间:2018-08-21 02:53:32

标签: c++ templates overloading sfinae

我对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)上吗?

1 个答案:

答案 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;
}