我试图找到问题C++ template non-type parameter type deduction问题的解决方案,该问题不涉及调用f的模板参数,但隐式选择模板参数的正确类型。
由于 constexpr 应该保证一个函数只包含编译时常量,并且在编译时进行评估(至少这是我认为的那样),我认为它可能是这个问题的解决方案。 所以我想出了这个:
template <class T, T VALUE> void f() {}
//first i tried this:
template <class T> auto get_f(T t) -> decltype( &f<T,t> ) { return f<T,t>; }
//second try:
template <class T> constexpr void (&get_f( T t ))() { return f<T,t>; }
int main()
{
get_f(10)(); //gets correct f and calls it
}
第一个版本生成以下错误:
error: use of parameter 't' outside function body
这真的令人困惑,因为在尾部返回类型的decltype语句中使用参数应该没问题?
第二版产生以下错误:
error: invalid initialization of non-const reference of type 'void (&)()'
from an rvalue of type '<unresolved overloaded function type>'
这有点令人困惑,因为我在f
中完全限定了get_f
。
如果我没有constexpr
,我会期待这种错误消息。那么,我对constexpr
的作用有一个错误的理解,或者GCC的C ++ 0x实现是否存在缺陷?
我正在使用GCC 4.6.2
答案 0 :(得分:5)
因为constexpr应该保证函数只包含compile 时间常量,并在编译时进行评估(至少那是什么 我认为它确实如此),我认为这可能是解决这个问题的方法。
constexpr
函数可以在常量表达式上下文中使用,但不限于一个。在这方面,它们不同于元函数和常规函数。考虑返回整数的后继的问题:
// Regular function
int f(int i)
{ return i + 1; }
// Regular metafunction
template<int I>
struct g {
static constexpr auto value = I + 1;
};
// constexpr function
constexpr int h(int i)
{ return i + 1; }
// Then...
{
// runtime context: the metafunction can't be used
int i;
std::cin >> i;
f(i); // Okay
g<i>::value; // Invalid
h(i); // Okay
// compile time context: the regular function can't be used
char a[f(42)]; // Invalid
char b[g<42>::value]; // Okay
char c[h(42)]; // Okay
}
constexpr
有其他用法(例如构造函数)但是当涉及constexpr
函数时,这是它的要点:某些函数应该在运行时和常量上下文中都可用,因为某些计算可用于都。可以计算i + 1
i
是编译时常量还是从std::cin
中提取。
这意味着在constexpr
函数体内,参数不本身是常量表达式。所以你所尝试的是不可能的。你的功能无法处理
int i;
std::cin >> i;
get_f(i); // what's the return type?
并且违规发生在这里:
constexpr auto get_f(T t)
-> decltype( &f<T,t> ) // <-
由于t
不是根据语言规则的常量表达式(无论如何,即使实际只传递常量表达式),它也不会显示为f
的第二个模板参数。
(在较大的图片中,它表示不,您不能使用 function 模板中的参数推导来方便地将非类型参数传递给类模板。)