C ++ 14variables模板:他们的目的是什么? 任何使用示例?

C ++ 14将允许创build模板化的variables。 通常的例子是一个variables“pi”,它可以被读取以得到各种types的math常数π的值( int为3; float为最可能的值)

除此之外,我们可以通过在模板化的结构或类中包装一个variables来实现这个function,这与types转换是如何结合的? 我看到一些重叠。

除了pi的例子之外,它是如何处理非constvariables的呢? 任何使用示例,了解如何充分利用此function以及它的目的是什么?

除了pi的例子之外,它是如何处理非constvariables的呢?

目前,它似乎为这个types分别实例化variables。 也就是说,你可以赋值10给n<int> ,这与模板定义不同。

 template<typename T> T n = T(5); int main() { n<int> = 10; std::cout << n<int> << " "; // 10 std::cout << n<double> << " "; // 5 } 

如果声明是const ,那么它是只读的。 如果它是一个constexpr ,就像所有的constexpr声明一样,在constexpr (ressions)之外没有多less用处。

除此之外,我们可以通过在模板化的结构或类中包装一个variables来实现这个function,这与混合types转换是如何结合的?

这意味着一个简单的build议。 我无法看出它是如何以显着的方式影响types转换的。 正如我已经说过的那样,variables的types是你实例化模板的types。 即, decltype(n<int>)是int。 decltype((double)n<int>)是double等等。

任何使用示例,了解如何充分利用此function以及它的目的是什么?

N3651提供了一个简洁的理由。

唉,现有的C ++规则不允许模板声明来声明一个variables。 有这个问题的众所周知的解决方法:

•使用类模板的constexpr静态数据成员

•使用constexpr函数模板返回所需的值

这些解决方法已经为数十年而闻名,并且有据可查。 标准类如std :: numeric_limits是典型的例子。 虽然这些解决方法并不完美,但是它们的缺点在一定程度上是可以忍受的,因为在C ++ 03时代,只有简单的内置types常量可以毫无限制地直接高效地支持编译时。 所有这一切都随着C ++ 11中的constexprvariables的采用而改变,这直接和有效地支持了用户定义types的常量。 现在,程序员正在使程序中的常量(类types)越来越明显。 因此,增加与解决方法相关的困惑和挫折。

“静态数据成员”的主要问题是:

•他们需要“重复”的声明:一旦进入课堂模板,一旦在课堂模板之外,提供“真正的”定义,以防止常规使用。

•由于提供两次相同的声明的必要性,程序员都感到困惑和困惑。 相比之下,“普通”常量声明不需要重复声明。

这个类别中的着名例子可能是numeric_limits的静态成员函数,或者是诸如boost::constants::pi<T>()等函数。Constexpr函数模板不会承受静态数据成员所具有的“重复声明”问题; 此外,他们提供function抽象。 但是,他们强迫程序员事先在定义站点select如何传递常量:通过const引用或简单的非引用types。 如果通过const引用传递,则常量必须在静态存储中被系统地分配; 如果通过非引用types,则常量需要复制。 复制对于内置types来说不是问题,但是对于用户定义types来说,它的价值语义并不仅仅是内build微型内置types(例如matrix,整数或大浮点等)的封装。相比之下,普通的“const(expr)variables不会遇到这个问题。 提供了一个简单的定义,常量是否需要在存储中进行布局的决定取决于使用情况,而不是定义。

我们可以通过在模板化的结构或类中包装一个variables来拥有这个特性

是的,但这将是无偿的语法盐。 对血压不健康。

pi<double>传达的意图比pi<double>::value更好。 简明扼要。 在我的书中,这足以说明和鼓励这种语法。

我想知道是否有可能:(假设可用的模板lambda)

 void some_func() { template<typename T> std::map<int, T> storage; auto store = []<typename T>(int key, const T& value) { storage<T>[key] = value; }; store(0, 2); store(1, "Hello"s); store(2, 0.7); // All three values are stored in a different map, according to their type. } 

现在,这有用吗?

作为一个简单的用法,请注意, pi<T>的初始化使用显式转换(显式调用一元构造函数),而不是统一的初始化。 这意味着,给定一个具有构造函数radians(double)的typesradians ,可以写pi<radians>

C ++ 14variables模板的另一个实际例子是当你需要一个函数来传递std::accumulate

 template<typename T> T const & (*maxer) (T const &, T const &) = std::max<T>; std::accumulate(some.begin(), some.end(), initial, maxer<float>); 

请注意,使用std::max<T>是不够的,因为它不能推断确切的签名。 在这个特定的例子中,你可以使用max_element来代替,但重点是有一整套函数共享这个行为。

那么,你可以用这个来编写这样的编译时间代码:

 #include <iostream> template <int N> const int ctSquare = N*N; int main() { std::cout << ctSquare<7> << std::endl; } 

这是相当于一个重大的改善

 #include <iostream> template <int N> struct ctSquare { static const int value = N*N; }; int main() { std::cout << ctSquare<7>::value << std::endl; } 

人们曾经写过在variables模板被引入之前执行模板元编程。 对于非types值,我们可以用C ++ 11和constexpr做到这一点,所以模板variables的优点是允许基于types的variables模板进行计算。

TL; DR:他们不允许我们做任何我们以前做不到的事情,但是他们使模板元编程减less了PITA。

    Interesting Posts