是否可以在内联constexpr函数中使用变量模板而不暴露变量模板本身?
例如,这会编译并运行:
template<typename T> constexpr T twelve_hundred = T(1200.0);
template<typename T>
inline constexpr T centsToOctaves(const T cents) {
return cents / twelve_hundred<T>;
}
但是这并没有编译:
template<typename T>
inline constexpr T centsToOctaves(const T cents) {
template<typename U> constexpr U twelve_hundred = U(1200.0);
return cents / twelve_hundred<T>;
}
原因似乎是在块范围内不允许使用模板声明(GCC提供了有关此信息的信息性错误消息,但Clang没有)。
为了更详细地重复动机,该函数是内联的并在标题中定义,并且我不想在包含标题的任何地方公开变量模板。
我想我可以定义一个详细命名空间并将变量模板放在那里,但是根本不公开变量模板会更好。也许这是不可能的。
答案 0 :(得分:3)
从标准我们得到:
模板声明是一种声明。 [...]。由变量的模板声明引入的声明是变量模板。 [...]
和
模板声明只能作为命名空间范围或类范围声明出现。
因此不,不允许。
如果你不想公开它,你仍然可以将它包装在一个类中,并使数据成员和成员函数都是静态的:
class C {
template<typename T>
static constexpr T twelve_hundred = T(1200.0);
public:
template<typename T>
static constexpr T centsToOctaves(const T cents) {
return cents / twelve_hundred<T>;
}
};
int main() {
C::centsToOctaves(42);
}
另一种可能的解决方案是:
class C {
template<typename T>
static constexpr T twelve_hundred = T(1200.0);
template<typename T>
friend inline constexpr T centsToOctaves(const T cents);
};
template<typename T>
inline constexpr T centsToOctaves(const T cents) {
return cents / C::twelve_hundred<T>;
}
int main() {
centsToOctaves(42);
}
plus centsToOctaves
不再是C
的成员函数,如评论中所述。
话虽如此,我不明白是什么阻止你这样做:
template<typename T>
inline constexpr T centsToOctaves(const T cents) {
return cents / T{1200};
}
答案 1 :(得分:0)
除了使用命名空间之外,您还可以将模板变量放入类中,并将其声明为私有。 不允许在函数范围内声明模板。
class Detail {
public:
template<typename T>
static constexpr T centsToOctaves(const T cents) {
return cents / twelve_hundred<T>;
}
private:
template<typename U>
static constexpr U twelve_hundred = U(1200.0);
};
// forwarding
template<typename T>
inline constexpr T centsToOctaves(const T cents) {
return Detail::centsToOctaves<T>(cents);
}
int main() {
centsToOctaves<int>(12);
return 0;
}
相依:
您可能不需要声明模板constexpr
变量。由于您无法在初始化后对其进行修改,因此替代实现可以直接使用文字:
template<typename T>
inline constexpr T centsToOctaves(const T cents) {
using U = T;
return cents / U(1200.0);
}
当你需要明确地专门化模板变量时,你可以专门化功能模板。
template <>
inline constexpr int centsToOctaves(const int cents) {
using U = int;
return cents / U(1200.0);
}
但遗憾的是,这个解决方案会生成一些重复的代码,可能会更糟糕。