【问题标题】:Type list does not want to compile类型列表不想编译
【发布时间】:2020-04-17 07:03:36
【问题描述】:

我正在尝试实现某种类型列表。我想知道为什么以下代码无法编译。 在我看来,它至少应该编译。

#include <iostream>
#include <type_traits>

struct Non_t {};

template<typename THead, typename TTail = Non_t>
struct Type_list
{
    using Head = THead;
    using Tail = TTail;
};

struct Conv1 {};
struct Conv2 {};
struct Conv3 {};

using Types = 
    Type_list<Conv1
>;

template<typename TTypeList, typename TWanted>
void dispatch()
{
    if constexpr (std::is_same<TTypeList, Non_t>::value)
    {
        std::cout << "Not found :( " << std::endl;
        
        return; 
    }
    
    using Head = typename TTypeList::Head;
    using Tail = typename TTypeList::Tail;
    using Wanted = TWanted;

    if constexpr (!std::is_same<Head, Wanted>::value)
    {
        dispatch<Tail, Wanted>();
    }
    else 
    {
       std::cout << "It works" << std::endl;
    }

}

int main()
{
    dispatch<Types, Conv3>();

    return 0;
}

只有当类型列表包含我需要的类型时,一切才能正常工作。

我尝试了 gcc 9.3 和 clang 10。

两个编译器都显示类似的错误消息:'error: no type named 'Head' in 'struct Non_t''

我尝试使用 clang 10 编译 https://godbolt.org/ 中的这段代码,我可以看到来自 clang 的以下提示:

注意:在函数模板特化的实例化中dispatch&lt;Type_list&lt;Conv1, Non_t&gt;, Conv3&gt;requested herex86-64 clang 10.0.0 #1

注意:在函数模板特化 dispatch&lt;Type_list&lt;Conv1, Non_t&gt;, Conv3&gt; 的实例化中请求 herex86-64 clang 10.0.0 #1

编辑: 只有当我将第一个'if语句'之后的函数部分包装到另一个else块中时,它才会编译。这是为什么呢?

【问题讨论】:

  • 您的using Head = ... 等出现在您的if constexpr 之后这一事实在这里没有任何区别。它必须仍然有效。您可以将 dispatch 的其余部分包装在 else 中。
  • 因为代码需要在编译时有意义。仅仅因为我们不会在运行时到达那段代码并不意味着我们可以编写无效代码而不会出现编译错误。

标签: c++ c++17 metaprogramming


【解决方案1】:

因为,正如错误所说,Non_t 没有名为 Head 的类型。您的 using Head = ... 声明是在您返回之后出现的这一事实并没有任何区别。

让我们看一个反例。

int main() {
    int i = 2;
    return i;

    i.thisIsNotValid();
}

这里我们会得到一个编译错误。在运行时我们永远不会到达那部分代码并不重要。这不是编译器所做的考虑。它只是确保所有编写的代码都是有效的并为其生成机器代码。

另一方面,使用if constexprelse 块我们告诉编译器在编译时评估某些东西并且只使用其中一个分支。另一个完全丢弃。

template<typename TTypeList, typename TWanted>
void dispatch()
{
    if constexpr (std::is_same<TTypeList, Non_t>::value)
    {
        std::cout << "Not found :( " << std::endl;

        return; 
    } else {

        using Head = typename TTypeList::Head;
        using Tail = typename TTypeList::Tail;
        using Wanted = TWanted;

        if constexpr (!std::is_same<Head, Wanted>::value)
        {
            dispatch<Tail, Wanted>();
        }
        else 
        {
           std::cout << "It works" << std::endl;
        }
    }
}

现在如果条件为真,函数的下半部分将在编译时被完全丢弃。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-08-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多