自定义开关功能中的大量神秘错误

时间:2017-05-11 14:35:07

标签: c++ templates boost c++17 boost-hana

我正在尝试根据the boost hana manual中的any类型切换示例编写任意值切换。

我之前已经成功完成了这项工作,但现在似乎无法完成。

我真的想弄清楚我的解决方案到底出了什么问题,所以不用多说了:

struct default_val{
    constexpr bool operator ==(const auto&) const noexcept{ return false; }
    constexpr bool operator !=(const auto&) const noexcept{ return true; }

    constexpr bool operator ==(default_val) const noexcept{ return true; }
    constexpr bool operator !=(default_val) const noexcept{ return false; }
};

template<typename Fn>
auto default_(Fn fn){
    return hana::make_pair(default_val{}, fn);
}

template<typename Val, typename Fn>
auto case_(Val val, Fn fn){
    return hana::make_pair(val, fn);
}

template<typename Val, typename Default>
decltype(auto) process(Val&&, Default &&def){
    return hana::second(std::forward<Default>(def))();
}

template<typename Val, typename Default, typename Case, typename ... Rest>
decltype(auto) process(Val &&val, Default &&def, Case &&cas, Rest &&... rest){
    if(std::forward<Val>(val) == hana::first(std::forward<Case>(cas)))
        return hana::second(std::forward<Case>(cas))();
    else
        return process(std::forward<Val>(val), std::forward<Default>(def), std::forward<Rest>(rest)...);
}

template<typename Val>
auto switch_(Val val){
    return [val](auto ... cases){
        auto cases_ = hana::make_tuple(cases...);

        auto default_ = hana::find_if(cases_, [](const auto &c){
            return
                hana::type_c<default_val> ==
                hana::type_c<std::decay_t<decltype(hana::first(c))>>;
        });

        static_assert(default_ != hana::nothing);

        auto rest_ = hana::filter(cases_, [](const auto &c){
            return
                hana::type_c<default_val> !=
                hana::type_c<std::decay_t<decltype(hana::first(c))>>;
        });

        return hana::unpack(rest_, [&](const auto &... rest){
            return process(val, default_, rest...);
        });
    }
}

这应该像any示例一样使用,但值为:

#include "myswitch.hpp"

int main(){
    std::string input;

    std::cin >> input;

    switch_(input)(
        case_("yowza", []{ std::cout << "where's the enthusiasm?\n"; }),
        case_("Yowza", []{ std::cout << "wat2hek\n"; }),
        case_("YOWZA!", []{ std::cout << "HooRah!\n"; }),

        default_([]{ std::cout << "Hello, World!\n"; })
    );
}

但是,在hana::find_if_t::operator()(Xs&&, Pred&&)中分配auto时,在扣除default_之前,我对switch_使用using System; using System.Collections.Generic; using System.Configuration; using System.Data; using System.Data.SqlClient; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; public partial class _Default : System.Web.UI.Page { SqlConnection con, con1; SqlCommand cmd, cmd1; DataSet ds, ds1; private int _x; public int X { get { return _x; } set { _x = value; } } public _Default() { con = new SqlConnection(); con.ConnectionString = ConfigurationManager.ConnectionStrings["GuitarItemsDBConnectionString2"].ToString(); cmd = new SqlCommand(); ds = new DataSet(); } protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { bindgridviewguitaritems(); } } public void getRowNumber(string brand, string model) { string query = string.Format("SELECT Rn FROM (SELECT *, ROW_NUMBER() OVER(ORDER BY id) AS Rn FROM guitarItems WHERE brand LIKE '{0}') x WHERE x.Model LIKE '{1}'",brand,model); con.Open(); cmd.Connection = con; cmd.CommandText = query; Int32 count = (Int32)cmd.ExecuteScalar(); //<----Here is the error X = count; con.Close(); } //Start of Gridview Code for Guitar Items private void bindgridviewguitaritems() { con.Open(); cmd.CommandText = "SELECT * FROM [guitarItems]"; cmd.Connection = con; SqlDataAdapter da = new SqlDataAdapter(cmd); da.Fill(ds); con.Close(); GridView1.DataBind(); } protected void GridViewBtn1_Click(object sender, EventArgs e) { Button btn = sender as Button; GridViewRow gridrow = btn.NamingContainer as GridViewRow; int id = Convert.ToInt32(GridView1.DataKeys[gridrow.RowIndex].Value.ToString()); string name = GridView1.Rows[gridrow.RowIndex].Cells[3].Text; string model = GridView1.Rows[gridrow.RowIndex].Cells[4].Text; getRowNumber(name,model); Label1.Text = X.ToString(); Label2.Text = name; Label3.Text = model; con.Open(); cmd.CommandText = "DELETE FROM [guitarItems] WHERE id=" + id; cmd.Connection = con; int a = cmd.ExecuteNonQuery(); con.Close(); if (a > 0) { bindgridviewguitaritems(); } System.IO.File.Delete(@"C:\Users\User1\Documents\Visual Studio 2015\WebSites\MusicStore\Pages\GuitarItems" + name + "Details" + id + ".aspx"); System.IO.File.Delete(@"C:\Users\User1\Documents\Visual Studio 2015\WebSites\MusicStore\Pages\GuitarItems" + name + "Details" + id + ".aspx.cs"); } //End of Gridview Code for Guitar Items 提出了一个长篇大论且含糊不清的错误。

有人能指出我在正确的方向吗?

1 个答案:

答案 0 :(得分:3)

根据Boost.Hana的谓词手册(强调我的):

  

一个名为谓词(k)的函数,其中k是结构的一个关键字,并返回k是否是被搜索元素的关键字。在库的当前版本中,谓词必须返回一个IntegralConstant,其中包含一个可以转换为bool的值

这是hana::find_ifhana::filter使用的谓词所必需的。

对于您的default_val类型,可以将实施更改为:

struct default_val {
    template <typename T>
    constexpr auto operator ==(const T&) const noexcept{ return hana::false_c; }
    template <typename T>
    constexpr auto operator !=(const T&) const noexcept{ return hana::true_c; }

    constexpr auto operator ==(default_val) const noexcept{ return hana::true_c; }
    constexpr auto operator !=(default_val) const noexcept{ return hana::false_c; }
};

我使用Clang 3.9运行您的代码,并且通过以下附加调整工作正常,可以打开default_可选值中的值。

        return hana::unpack(rest_, [&](const auto &... rest){
        return process(val, *default_, rest...);
                         // ^ Note the added dereference operator here