基于类型的任意属性的函数重载不起作用

时间:2012-03-04 17:02:44

标签: c++ generic-programming sfinae

在下面的示例中,我需要提取一些值。我有一个高效的提取器,可以使用内置类型,以及一个可以处理所有内容的低效模板。要在这些中进行选择,我想使用Function Overloading Based on Arbitrary Properties of Types。这是我的代码:

#include <string>
#include <iostream>

class extractor
{
public:
    static void extract(const bool& val) { std::cout << "Specialized extractor called" << std::endl; }
    static void extract(const double& val) { std::cout << "Specialized extractor called" << std::endl; }
};

template <typename T>
void extract_generic(const T& value) { std::cout << "Generic extractor called" << std::endl; }


template <typename T> struct is_extractor_native { static const bool val = false; };
template<> struct is_extractor_native<bool> {static const bool val = true; };
template<> struct is_extractor_native<double>  {static const bool val = true; };


template <bool B, class T = void>
struct enable_if {
    typedef T type;
};

template <class T>
struct enable_if<false, T> {};

template <typename T>
struct extract_caller
{

    //line 32 below
    static void extract(const T& val, typename enable_if<is_extractor_native<T>::val>::type * = 0)
    {
            extractor::extract(val);
    }

    //line 37 below
    static void extract(const T& val, typename enable_if<!is_extractor_native<T>::val>::type * = 0)
    {
            extract_generic(val);
    }
};



int main(void)
{
    std::string string_value("hello");
    double double_value(.123);

    std::cout << "native extractor for std::string: " << (int)is_extractor_native<std::string>::val << std::endl;
    std::cout << "native extractor for double:      " << (int)is_extractor_native<double>::val << std::endl;

    extract_caller<std::string>::extract(string_value);
    extract_caller<double>::extract(double_value);

    return 0;
}    

当我构建编译器时抱怨:

g++     main.cpp   -o main
main.cpp: In instantiation of ‘extract_caller<std::basic_string<char> >’:
main.cpp:50:29:   instantiated from here
main.cpp:32:14: error: no type named ‘type’ in ‘struct enable_if<false, void>’
main.cpp: In instantiation of ‘extract_caller<double>’:
main.cpp:51:24:   instantiated from here
main.cpp:37:14: error: no type named ‘type’ in ‘struct enable_if<false, void>’
make: *** [main] Error 1

当注释掉提取并且只打印了特征时,我得到了正确的结果:

./main
native extractor for std::string: 0
native extractor for double:      1

在错误列表中,您可以看到double编译器在第32行传递原型,转到37并打印错误。问题是,为什么SFINAE原则不适用于此?

2 个答案:

答案 0 :(得分:2)

SFINAE仅在某些错误(如您所拥有的错误)发生在声明部分时才有效。在您的情况下,它们发生在定义中。在enable_if的情况下,您必须重写代码,以便在声明中使用struct extract_caller

答案 1 :(得分:0)

通过修复问题doublep得到的代码:

struct extract_caller
{
    template <typename T>
    static void extract(const T& val, typename enable_if<(bool)is_extractor_native<T>::val>::type * = 0)
    {
            extractor::extract(val);
    }

    template <typename T>
    static void extract(const T& val, typename enable_if<!(bool)is_extractor_native<T>::val>::type * = 0)
    {
            extract_generic(val);
    }
};

这可以用作

extract_caller::extract(string_value);
extract_caller::extract(double_value);