【问题标题】:method template overload in class template using sfinae使用 sfinae 的类模板中的方法模板重载
【发布时间】:2015-09-11 20:59:36
【问题描述】:

我正在尝试使用 SFINAE 创建一个带有模板重载方法的模板类,以排除未使用的方法,但在阅读了许多帖子和数小时的工作后,我不知道哪个是我的错误。

我的想法是创建一个有 4 个参数的类模板,其中 3 个是可选参数,其中 2 个可选参数将在重载方法中使用,并且只会编译正确的版本,就像这样(对不起,我尝试使用语法高亮,但我不知道怎么做)

template<char const q[], typename P1 = void, typename P2 = void, typename P3 = void>
class query
{
    char const * const value;
  public:
    query() : value(q) {};
    template<typename returnType, something else>
    returnType execute(P1 data1, P2 data2) { ..... };
    template<typename returnType, something else>
    returnType execute(P2 data2) { ..... };
    template<typename returnType, something else>
    returnType execute(P1 data1) { ..... };
    template<typename returnType, something else>
    returnType execute() { ..... };
}
constexpr char const q_str[] = "hola mundo";

class A {};
int main()
{
    query<q_str> v1;
    query<q_str, A> v2;

    A param;

    bool rc = v2.execute<bool>(param); << I expect to use the method execute(P1 data1)
    return 0;
}

所以,我的代码是这样的

template<char const q[], typename Tin = void, typename Tout = void, typename Twhere = void>
class query
{
    char const * const value;
public:
    typedef Tin ty_bind_in;
    typedef Tout ty_bind_out;

    query() : value(q) {};

    template<typename returnType,
             typename in = Tin,
             typename cond = typename std::enable_if< std::is_class<in>::value, void >::type>
    returnType execute(Tin &p_data)
    {
        returnType rs;
        return rs;
    };

    template<typename returnType>
    returnType execute()
    {
        returnType rs;
        return rs;
    };
};

constexpr char const q_str[] = "hola mundo";

class A {};

int main()
{
    query<q_str, A> q1;
    query<q_str> q2;

    return 0;
}

我正在使用这个版本的 gcc

gcc (Debian 4.9.2-10) 4.9.2

我要编译的行是这样的

g++ -std=c++11 -g stack.cpp

我得到这个错误

stack.cpp: In instantiation of ‘class query<((const char*)(& q_str))>’:
stack.cpp:40:15:   required from here
stack.cpp:19:13: error: forming reference to void
  returnType execute(Tin &p_data)
             ^

如您所见,我一声明变量就会收到错误消息。可能我做错了什么,但我不知道问题出在哪里。

编辑 14/09: 再次嗨,在 Barry 的解释之后,我解决了这个问题并继续我的想法,所以我尝试为方法执行添加两个重载,第一个是这个(想法:当模板参数 Tin 和 Twhere 为 != void 时,此方法将起作用)

template<typename returnType,
         typename in = Tin,
         typename cond2 = typename std::enable_if<std::is_class<in>::value >::type, 
         typename where = Twhere,
         typename cond = typename std::enable_if< std::is_class<where>::value >::type>
returnType execute(in &p_data, where &p_where)
{
    returnType rs;
    return rs;
};

第二个是this(想法:当模板参数Twhere为!= void时,此方法将起作用)

template<typename returnType,
         typename where = Twhere,
         typename cond = typename std::enable_if< std::is_class<where>::value >::type>
returnType execute(where &p_data)
{
    returnType rs;
    return rs;
};

我收到以下错误

stack.cpp:39:13: error: ‘template<const char* q, class Tin, class Tout, class Twhere> template<class returnType, class where, class cond> returnType query<q, Tin, Tout, Twhere>::execute(where&)’ cannot be overloaded
  returnType execute(where &p_data)
             ^
stack.cpp:19:13: error: with ‘template<const char* q, class Tin, class Tout, class Twhere> template<class returnType, class in, class cond> returnType query<q, Tin, Tout, Twhere>::execute(in&)’
  returnType execute(in &p_data)

在我看来,这是因为 Tin 和 Twhere 的重载版本在参数方面看起来相等,但我不知道如何更正代码。

一些想法?

提前谢谢你 最好的问候

【问题讨论】:

  • 您的第一个代码块是否与问题相关?你介意我把它删掉吗?
  • 嗨,Barry,我的第一个代码块只是一个例子来说明我的意图,因为我的真实代码可能有错误,实际上可能有错误

标签: c++ templates overloading sfinae


【解决方案1】:

当你写这个函数时:

template <....>
returnType execute(Tin &p_data)

如果Tinvoid,则格式错误。虽然由于 SFINAE 将始终排除该条件,但函数本身仍然是格式错误的,并且允许编译器在那里出错。相反,您应该在那里使用您的模板参数:

template<typename returnType,
         typename in = Tin,
         typename cond = typename std::enable_if< std::is_class<in>::value, void >::type>
returnType execute(in& p_data)
                   ^^^^

旁注,enable_if 中的额外 void 是不必要的,因为这是默认设置。如果你有一个 C++14 编译器,你应该更喜欢std::enable_if_t,如果你没有,你应该在某个地方写那个别名,只是为了可用性。那会让你写:

template<typename returnType,
         typename in = Tin,
         typename = enable_if_t<std::is_class<in>::value>>
returnType execute(in& p_data)

更少的字符,更容易理解重要部分。

【讨论】:

  • 哇......像往常一样,你的答案非常好,非常清楚。非常感谢!!! ..关于额外的空白,是真的,是不必要的,但我之所以这么说是因为我需要在我的代码中非常明确,你知道我与模板相关的技能还需要大量的工作。再次感谢您!
  • @Trungus Explicit 很棒,但对于enable_if - 它不太重要。在这里,您没有将它用于void - 您甚至不关心类型是什么,您只是将它用于enable_if 部分。排除它只会让其他人更容易看到你在做什么。
  • 我明白,我会尽量考虑;)...感谢您的帮助和建议:D
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-01
  • 1970-01-01
  • 2018-06-08
  • 2019-01-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多