【问题标题】:Specializing struct template using enable_if使用 enable_if 专门化结构模板
【发布时间】:2017-02-23 04:19:07
【问题描述】:

我正在尝试创建一个模板类,它将实现具有不同签名的回调,具体取决于它是使用一种类型还是两种类型进行实例化。

struct NoIntermediate
{
};

template<typename R, typename I>
struct ParserCallbackSwitch
{
     using type = std::function<bool(const std::string &, R&, I&)>;
}

template<typename R, typename I = NoIntermediate>
class OtherClass
{
public:
    typedef ParserCallbackSwitch<R, I>::type ParserType;

}

现在我想添加代码,如果在实例化“OtherClass”时未指定我,则 ParserCallbackSwitch 将是:

template<typename R, typename I>
struct ParserCallbackSwitch
{
      using type = std::function<bool(const std::string &, R&)>;
}

请注意,在这种情况下 ParserCallbackSwitch::type 是一个只有两个参数的函数。

我希望能够做到以下几点:

OtherClass<int, float> p; // p::ParserType = std::function<bool(std::string &, int &, float &);
OtherClass<int> q;        // q::ParserType = std::function<bool(std::string &, int &);

当 I 的类型为 NoIntermediate(即未指定 I)时,我不知道如何部分指定 ParserCallbackSwitch

解决方案:基于以下回复。这是我最终使用的代码。

struct NoIntermediate {};

template<typename R, typename I = NoIntermediate>
struct ParserCallbackSwitch
{
    using type = std::function<bool(const std::string &, R&, I&)>;
};

template<typename R> 
struct ParserCallbackSwitch<R, NoIntermediate>
{
    using type = std::function<bool(const std::string &, R&)>;
};

template<typename R, typename I = NoIntermediate>
class OtherClass
{
   public:
   typedef ParserCallbackSwitch<R, I>::type ParserType;
}

【问题讨论】:

标签: c++ sfinae enable-if


【解决方案1】:

所以!您没有正确专门化模板。您正在定义两个恰好具有相同名称的不相关的类模板。

有多种方法可以按照您的建议进行。这给了最不专业的模板一个参数包。

#include <functional>
#include <type_traits>

template<typename... S>
struct OtherClass;

template<typename R, typename I>
struct OtherClass<R, I> {
    using ParserType = std::function<bool(std::string&, R&, I&)>;
};

template<typename R>
struct OtherClass<R> {
    using ParserType = std::function<bool(std::string&, R&)>;
};

int main(void) {
    static_assert(std::is_same<OtherClass<int, float>::ParserType,
                            std::function<bool(std::string&, int&,
                                                float&)>>(),
                "Something wrong here.");
    static_assert(std::is_same<OtherClass<int>::ParserType,
                            std::function<bool(std::string&, int&)>>(),
                "Hmmmmmm.");
    return 0;
}

您在参数中使用默认类型的想法也有效,但您的语法稍有偏差。这就是它的样子。

#include <functional>
#include <type_traits>

template<typename R, typename I = void>
struct OtherClass {
    using ParserType = std::function<bool(std::string&, R&, I&)>;
};

template<typename R>
struct OtherClass<R, void> {
    using ParserType = std::function<bool(std::string&, R&)>;
};

int main(void) {
    static_assert(std::is_same<OtherClass<int, float>::ParserType,
                            std::function<bool(std::string&, int&,
                                                float&)>>(),
                "Something wrong here.");
    static_assert(std::is_same<OtherClass<int>::ParserType,
                            std::function<bool(std::string&, int&)>>(),
                "Hmmmmmm.");
    return 0;
}

【讨论】:

  • 关闭,但我不能使用 void,因为在代码的另一部分我使用它作为函数的参数。如果我使用 struct NoIntermediate {}; 的默认值,第二个效果很好。我将把我最终使用的代码放在上面。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-02
  • 1970-01-01
相关资源
最近更新 更多