【问题标题】:Expression Template - Failed to specialize function template表达式模板 - 无法专门化函数模板
【发布时间】:2012-06-15 01:54:44
【问题描述】:

我试图制作一些表达式模板作为this question 的答案,但我遇到了编译器错误,我无法弄清楚。我现在的 SSCCE 已经很小了

template<class sub_expr>
class inherit2 : private sub_expr { //line 3
public:
    inherit2(sub_expr rhs) : sub_expr(rhs) {}
    template<class T>
    auto operator()(const T& v) const ->decltype(sub_expr::operator()(v)) //line 7
    {return sub_expr::operator()(v);}
};

class expression_parameter {
public:
    template<class T>
    const T& operator()(const T& v) const {return v;}
};

int main() {
    expression_parameter x;
    auto expr0 = x;
    int res0 = expr0(3); //line 20
    auto expr1 = inherit2<expression_parameter>(x); //line 21
    int res1 = expr1(3); //line 22
    return 0;
}

当我用 MSVC10++ 编译时,我得到这个错误:

f:\code\utilities\exprtemplate\exprtemplate\sscce.cpp(22): error C2893: Failed to specialize function template ''unknown-type' inherit2<sub_expr>::operator ()(const T &) const'
with
[
    sub_expr=expression_parameter
]
With the following template arguments:
'int'

当我使用 GCC 4.6.3 编译时:

sscce.cpp: In instantiation of 'inherit2<expression_parameter>':
sscce.cpp:21:47:   instantiated from here
sscce.cpp:3:7: warning: base class 'class expression_parameter' has a non-virtual destructor [-Weffc++]
sscce.cpp: In function 'int main()':
sscce.cpp:22:20: error: no match for call to '(inherit2<expression_parameter>) (int)'
sscce.cpp:3:7: note: candidate is:
sscce.cpp:7:10: note: template<class T> decltype (sub_expr:: operator()(v)) inherit2::operator()(const T&) const [with T = T, sub_expr = expression_parameter, decltype (sub_expr:: operator()(v)) = decltype (expression_parameter::operator()(v))]
sscce.cpp:20:6: warning: unused variable 'res0' [-Wunused-variable]
sscce.cpp:22:6: warning: unused variable 'res1' [-Wunused-variable]

最后是 Clang 3.1

sscce.cpp(22,12) :  error: no matching function for call to object of type 'inherit2<expression_parameter>'
        int res1 = expr1(3);
                   ^~~~~
sscce.cpp(7,9) :  note: candidate template ignored: substitution failure [with T = int]
    auto operator()(const T& v) const ->decltype(sub_expr::operator()(v))
         ^

总而言之:它似乎我弄错了decltype,但我想不出正确的方法。谁能帮我找出导致这些错误的原因?

【问题讨论】:

  • 大胆猜测:你试过decltype( lhs()( v ) * rhs()( v ) )吗?
  • @ildjarn:我没有意识到这一点,尽管事后看来它是完全有道理的。谢谢。
  • @dirkgently:好主意,但似乎没有效果。当我尝试lhs(v) 时,编译器认为这是一个构造。
  • @dirkgently:一旦我加入了 Luc 对模糊基本问题的修复,那么你的评论就解决了我的问题。愿意将其发布为答案吗?

标签: c++ templates c++11 expression-trees


【解决方案1】:

我从 GCC 得到的一些错误提示我存在一个模棱两可的基础。即,expression_multiply&lt;expression_parameter, expression_parameter&gt; 具有 expression_parameter 作为(直接)基础,inherit_again&lt;expression_parameter&gt; 本身具有 expression_parameter 作为基础。这意味着lhs::operator()expression_multiply&lt;expression_parameter, expression_parameter&gt; 的范围内是不明确的(其中lhs 实际上是expression_parameter

需要进一步修复,因为operator() 的返回类型中需要this,导致以下修复:

// Instead of inherit_again
template<int N, class sub_expr>
class base : public sub_expr {
public:
    base(sub_expr rhs): sub_expr(std::move(rhs)) {}
};

template<class lhs_given, class rhs_given>
class expression_multiply: private base<0, lhs_given>, private base<1, rhs_given> {
    typedef base<0, lhs_given> lhs;
    typedef base<1, rhs_given> rhs;
public:
    expression_multiply(lhs_given l, rhs_given r):lhs(std::move(l)), rhs(std::move(r)) {}
    template<class T>
    auto operator()(const T& v) const
    -> decltype(this->lhs::operator()(v) * this->rhs::operator()(v))
    {
        return lhs::operator()(v) * rhs::operator()(v);
    }
};

不知道编译器是否对这两个“修复”的需求进行了纠正。

【讨论】:

  • 这个可以在你的机器上编译吗?因为在我的机器上我得到“error: invalid use of 'this' at top level”。不过,base 类型的索引是个好主意,谢谢。
  • 我重新安排了一些事情并想出了如何大大简化我的 SSCCE。
  • @MooingDuck 它是可编译的,是的。我不记得是否允许this 出现在那里,但无论如何你都可以用std::declval&lt;expression_multiply const&amp;&gt;() 代替它,或者将整个调用更改为例如std::declval&lt;lhs const&amp;&gt;()(v)std::declval&lt;lhs const&amp;&gt;().operator()(v).
  • 我对此进行了测试,它可以在 GCC 和 Clang 中编译,尽管 MSVC 会炸毁它。 dirkgently 有一个适用于所有 3 的解决方法,但我会将您的标记为最佳答案,因为 (A) 它不止一个句子,并且 (2) 您发现了问题,并用至少一个编译器解决了它。
【解决方案2】:

这是 Luc 修复的附录。使用:

decltype(std::declval<lhs>()( v ) * std::declval<rhs>()( v ) )

帮助编译器轻松推断类型。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多