c++ - 使用默认模板参数引入派生类型

标签 c++ templates c++11

我有一个模板,我需要在其中使用从用户提供的类型派生的类型 Tnoexcept 内说明符多次。在下面的示例中,我需要使用 T 的衰减类型多次。天真的方法是:

// in this case 
template <typename T>
void foo(T&& t) noexcept(   noexcept(typename std::decay<T>::type(std::forward<T>(t)))
                         && noexcept(std::declval<typename std::decay<T>::type>() = std::forward<T>(t)))
{
  typedef typename std::decay<T>::type DT;
  /* ... */
}

需要重复typename std::decay<T>::type所以常常显得过于冗长。我可以用 DT 替换整个表达式类型,但不幸的是,这仅在函数体中可用。

最简单的介绍DT在函数体之前我能想到的是这样的:

template <typename T, typename DT = typename std::decay<T>::type>
void foo(T&& t) noexcept(   noexcept(DT(std::forward<T>(t)))
                         && noexcept(std::declval<DT>() = std::forward<T>(t)))
{
  /* DT also available here... */
}

不过,仅仅为了这个目的而添加另一个模板参数感觉是错误的。所以,我的问题:

  • 添加额外的默认模板参数是否有任何有害的副作用?
  • 这被认为是不好的做法吗?
  • 有没有其他方法可以引入DT以便它在 noexcept 中可用说明符?

编辑: 在我看来,真正的问题并不是获得对 DT 的访问权。 ,但降低了 noexcept 的复杂性完全表达(因为它用于许多函数)。我在下面添加了一个答案,为此目的创建了一个自定义特征。

最佳答案

我觉得我无法回答第二个问题,即它是否被视为不良做法,因为我认为这些是根据具体情况做出的决定。对您有用的东西可能对其他人不起作用。

您应该了解的是备选方案。如果调用者认为他需要显式提供两个模板参数,则添加另一个默认模板参数会更改 API 并打开潜在的错误。这不太可能,AFAICS 通常不是一个大问题。 API 修改 OTOH 可能是个问题。

在这种情况下,您可能会考虑将 foo 变成 foo_impl 的转发器,并且只有 foo_impl 具有第二个默认模板参数。这通常有助于保持 API 清洁。如果您将 foo_impl 移动到匿名命名空间(或者移动到 private 第二个,如果这是在一个类中)编译器可能会也可能不会内联它,甚至生成的代码看起来像你的移动详细和明确的版本。

namespace
{
    template <typename T, typename DT = typename std::decay<T>::type>
    void foo_impl(T&& t) noexcept(   noexcept(DT(std::forward<T>(t)))
                                  && noexcept(std::declval<DT>() = std::forward<T>(t)))
    {
       /* DT also available here... */
    }
}

// clean API
template <typename T>
void foo(T&& t) noexcept(noexcept(foo_impl(std::forward<T>(t))))
{
    return foo_impl(std::forward<T>(t));
}

关于c++ - 使用默认模板参数引入派生类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19043652/

相关文章:

c++ - 无法使用SDL编译:体系结构x86_64的 undefined symbol

c++ - 指针的初始化

android - 如何将 32 位 .so 文件转换为适用于 Android 的 64 位 .so 文件

c++ - EASTL 性能

C++:模板特化,std 映射选择了错误的特化

c++ - 对嵌套类使用类型别名

c# - 从 Java 到 C++ 或 C#

c++ - LNK2019错误未解析的外部符号

c++ - 将类查看到容器中

c++ - 智能指针而不是指针