c++ - 成员到指针变量仅在带有-std = c++ 17的Clang中被接受为函数模板参数

标签 c++ c++14 c++17 language-lawyer

https://godbolt.org/z/o7rBT9

这可以使用-std=c++14在Clang上编译良好

struct Vecs
{
    enum class VecIndex { first, second };
    std::vector<int> vec1, vec2;

    template <VecIndex> struct vecForIndex;
    template <> struct vecForIndex<VecIndex::first> {
        static constexpr auto vecPtr = &Vecs::vec1;
    };
    template <> struct vecForIndex<VecIndex::second> {
        static constexpr auto vecPtr = &Vecs::vec2;
    };

    template <std::vector<int> Vecs::*vecPtr>
    static void work() {}

    static void workSpecificVec()  { 
        work<&Vecs::vec1>(); 
    }
};

但是这个版本的workSpecificVec不会:
static void workSpecificVec()  { 
    work<vecForIndex<VecIndex::first>::vecPtr>(); 
}

后者确实使用-std=c++17进行编译。

为什么?

附言gcc和msvc都不能使用任何标准来编译上述内容。 IIUC是类范围have been allowed since c++14中的显式特化,因此无论是编译器还是我的理解似乎都是一个问题。

最佳答案

类范围的显式特化是C++ 17的一项功能(CWG 727不是针对C++ 14的DR,它是C++ 17的新增功能)gcc尚未实现(这是gcc bug 85282)。

这里还有C++ 17的另一个功能-扩大了可以用作非类型模板参数的参数类型(N4198进行解释,N4268进行措辞)。在C++ 14中,vecForIndex<VecIndex::first>::vecPtr不是允许的非类型模板参数,因为指向成员的指针(如您的示例)的唯一允许的参数是:

  • 精确表示为&T::X形式的表达式(例如,从字面上看是该语法)
  • 一个任意常量表达式,其结果为空指针值。

  • 就是这样。 vecForIndex<VecIndex::first>::vecPtr都不是这些东西,因此它在C++ 14中格式不正确。在C++ 17中,对非类型模板参数的限制要宽松得多,因此可以正常工作。

    如果您希望所有这些内容都保留在类主体中,则可以使用带有if constexpr的功能模板,而不是专用的类模板。它的代码也更少:
    template <VecIndex I>
    constexpr auto vecForIndex()
    {
        if constexpr (I == VecIndex::first) return &Vecs::vec1;
        else if constexpr (I == VecIndex::second) return &Vecs::vec2;
    }
    

    然后:
    static void workSpecificVec()  { 
        work<vecForIndex<VecIndex::first>()>(); 
    }
    

    关于c++ - 成员到指针变量仅在带有-std = c++ 17的Clang中被接受为函数模板参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61348289/

    相关文章:

    c++ - 如果我在 C++ 中以 new 的放置形式使用的内存不足会怎样?

    c++ - 将自动分配的 std::vector 转换为动态分配的 std::vector 而无需复制开销

    c++ - 对 int/float 进行排序的最快并行 C++ 排序实现是什么?

    c++ - 如何避免这种类似单例的设计模式?

    c++ - MPI 分布层

    c++ - 链接错误 : undefined reference to `avahi_alternative_service_name'

    c++ - 如何在不破坏现有客户端代码(pre c++17)的情况下将类转换为模板类?

    c++ - Black Magic 使用 Initializer_list 和包扩展

    c++ - 如何在 std::map 中尝试放置 POD 结构?

    c++ - 如何为序列和关联容器实现通用功能?