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/