Bar*_*icz 11 c++ templates c++11
非类型模板参数显然不是类型,例如:
template<int x>
void foo() { cout << x; }
Run Code Online (Sandbox Code Playgroud)
除了int
那种情况还有其他选择,我想谈谈这个很好的答案.
现在,有一件事让我感到困惑:结构.考虑:
struct Triple { int x, y, z; };
Triple t { 1, 2, 3 };
template<Triple const& t>
class Foo { };
Run Code Online (Sandbox Code Playgroud)
现在,使用普通的非类型引用语义,我们可以编写:
Foo<t> f;
Run Code Online (Sandbox Code Playgroud)
什么是这里值得注意的是,t
不能将constexpr
甚至const
,因为这意味着内部联动,这基本上意味着,该行不会编译.我们可以通过声明绕过t
的const extern
.这本身可能有点奇怪,但真正令我惊讶的是为什么这是不可能的:
Foo<Triple { 1, 2, 3 }> f;
Run Code Online (Sandbox Code Playgroud)
我们从编译器得到了一个非常好的错误:
error:
Triple{1, 2, 3}
不是类型的有效模板参数,const Triple&
因为它不是左值.
我们不能Triple
在模板中按值指定,因为这是不允许的.但是,我无法理解这一小段代码的真正问题.不允许使用结构作为值参数的原因是什么.如果我可以使用三个int
s,为什么不使用三个整数的结构?如果它只有普通的特殊成员,那么它在处理方面不应该只是三个变量.
小智 16
c++20用户的更新答案:
C++20 添加了对类文字(带有constexpr
构造函数的类)非类型模板参数的支持,这将允许原始问题中的示例工作,前提是模板参数被值接受:
template<Triple t> // Note: accepts t by value
class Foo { };
// Works with unnamed instantiation of Triple.
Foo<Triple { 1, 2, 3 }> f1 {};
// Also works if provided from a constexpr variable.
constexpr Triple t { 1, 2, 3 };
Foo<t> f2 {};
Run Code Online (Sandbox Code Playgroud)
此外,Triple { 1, 2, 3 }
整个程序中的所有模板参数实例都将引用相同的静态存储持续时间对象:
template<Triple t1, Triple t2>
void Func() {
assert(&t1 == &t2); // Passes.
}
constexpr Triple t { 1, 2, 3 };
int main()
{
Func<t, Triple {1, 2, 3}>();
}
Run Code Online (Sandbox Code Playgroud)
命名类类型 T 的非类型模板参数的标识符表示类型为 const T 的静态存储持续时间对象,称为模板参数对象,其值是相应模板参数在转换为类型后的值模板参数。同类型程序中的所有这些模板参数具有相同的值表示相同的模板参数对象。
请注意,模板参数允许的类文字类型有很多限制。有关更多详细信息,请查看我写的解释文字类 NTTP 的用法和限制的博客文章:文字类作为 C++20 中的非类型模板参数。
R. *_*des 13
我认为"因为mikta的痛苦才能正确指定和实施"是我们没有这个的主要原因.当然,很容易让这一点工作,但人们会抱怨使用结构模板参数在其他模板参数所做的所有相同情况下都不起作用(考虑部分特化,或者如何处理operator==
).
在我看来,得到整个蛋糕太乱了,只得到一小块就不够令人满意了,可能更令人沮丧.只做这个小小的工作不会给我比以下更多的功能,它具有开箱即用的各种东西(包括部分特化)的额外优势.
template <int X, int Y, int Z>
struct meta_triple {
// static value getters
static constexpr auto x = X;
static constexpr auto y = Y;
static constexpr auto z = Z;
// implicit conversion to Triple
constexpr operator Triple() const { return { X, Y, Z }; }
// function call operator so one can force the conversion to Triple with
// meta_triple<1,2,3>()()
constexpr Triple operator()() const { return *this; }
};
Run Code Online (Sandbox Code Playgroud)
您可以定义t
为const extern
,给它外部链接.然后构造工作:
struct Triple { int x, y, z; };
const extern Triple t { 1, 2, 3 };
template<Triple const& t>
class Foo { };
Foo<t> f;
Run Code Online (Sandbox Code Playgroud)
实例.
您无法将临时值传递给引用模板参数的原因是该参数是引用.如果模板参数是const int&
并且您尝试传递,则会收到相同的错误7
.例子.
编辑
三个int
s和一个包含三个int
s 的结构之间的区别在于,所有类型的文字int
都是相同的值(所有出现7
的只有七个),而每个构造函数对结构的调用在概念上创建了一个新实例.拿这个假设的例子:
template <Triple t>
struct Foo {};
Foo<Triple {1, 2, 3}> f1;
Foo<Triple {1, 2, 3}> f2;
Run Code Online (Sandbox Code Playgroud)
我认为它会引入额外的复杂性来将这两个构造函数调用"匹配"到同一个模板实例中.
归档时间: |
|
查看次数: |
5279 次 |
最近记录: |