【问题标题】:SFINAE for cast operator演员表操作员的 SFINAE
【发布时间】:2017-12-22 23:47:26
【问题描述】:

我有一个类,它包装一个枚举并为其提供字符串转换。现在我介绍了模板参数“fastStringConvert”,它控制如何使用 SFINAE 进行转换(可在此处找到:how can I use std::enable_if in a conversion operator?)。该代码在 MSVC 下编译,但在 GCC 和 Clang 下编译失败。

error: no type named ‘type’ in ‘struct std::enable_if<false, void>’

可能是什么问题,我应该如何更改代码?

以下或此处代码的相关部分:http://rextester.com/SYC74124

#include <map>
#include <string>
#include <type_traits>

template <
    class SubClass, 
    typename EnumType, 
    bool fastStringConvert = true
>
class SmartEnum
{
public:
    template <
        typename SFINAEPostponer = EnumType,
        typename = typename std::enable_if<fastStringConvert, void>::type
    >
    explicit operator const std::string&() const 
    {
        auto name = SubClass::names().find((int)value);
        if (name != SubClass::names().end())
        {
            return name->second;
        }
        else
        {
            static const std::string na("n.a.");
            return na;
        }
    }

    template <
        typename SFINAEPostponer = EnumType,
        typename = typename std::enable_if<!fastStringConvert, void>::type
    >
    explicit operator const std::string() const
    {
        auto name = SubClass::names().find((int)value);
        if (name != SubClass::names().end()) return name->second;
        else return std::to_string((int)value);
    }

protected:
    typedef const std::map<int, std::string> Names;
    EnumType value;
};


enum class Foo_type : int { a, b, c }; 

struct Foo : SmartEnum<Foo, Foo_type, true>
{ 
    typedef SmartEnum<Foo, Foo_type, true> Base; 

    static const Base::Names &names() 
    { 
        static const Base::Names names = { { 0, "a" }, { 1, "b" }, { 2,"c" }}; 
        return names; 
    } 
};

【问题讨论】:

    标签: c++ gcc sfinae enable-if typecast-operator


    【解决方案1】:

    您必须使用方法中的模板参数,否则您会遇到硬错误,例如:

    template <
        typename SFINAEPostponer = EnumType,
        bool Cond = !fastStringConvert,
        typename = typename std::enable_if<Cond, void>::type
    >
    explicit operator const std::string() const
    

    顺便说一句,最好使用enable_if 作为类型而不是默认值(以允许禁用部分):

    template <
        typename SFINAEPostponer = EnumType,
        bool Cond = !fastStringConvert,
        typename std::enable_if<Cond, void>::type* = nullptr
    >
    explicit operator const std::string() const
    

    【讨论】:

    • 谢谢,它有帮助。我什至不需要这样的第一个参数。
    • 你能解释一下这两种解决方案有什么区别吗?
    • @simon 你不能只根据模板参数的默认值重载函数,就像你不能根据参数的默认值重载函数一样。
    • 我最近观看了 Stephan T. Lavavej 的视频,他建议使用 typename std::enable_if&lt;Cond, void**&gt;::type = nullptr,因为没有什么可以隐式转换为 void**
    猜你喜欢
    • 2011-08-15
    • 1970-01-01
    • 2018-11-10
    • 2011-01-25
    • 1970-01-01
    • 1970-01-01
    • 2023-03-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多