C++模板元编程,"静态如果"解决方法 - 可以改进吗?

Vit*_*meo 7 c++ static templates if-statement c++11

我有一个扫描用户文件系统的函数,用路径填充向量,然后对其进行排序.由于用户应该能够在编译时决定是否要求向量排序,我使用模板和帮助程序类来代替非常期望(但不存在)的"静态if".

考虑以下代码:

enum class Sort{Alphabetic, Unsorted};  

template<Sort TS> struct SortHelper;
template<> struct SortHelper<Sort::Alphabetic>
{
    static void sort(vector<string>& mTarget) { sort(begin(mTarget), end(mTarget)); }
};
template<> struct SortHelper<Sort::Unsorted>
{
    static void sort(vector<string>&) { }
};

template<Sort TS> struct DoSomethingHelper
{
    static void(vector<string>& mTarget)
    {
         // do something with mTarget
         SortHelper<TS>::sort(mTarget);
    }   
};
Run Code Online (Sandbox Code Playgroud)

我上面编写的代码与原始代码相比有了很大的简化,它采用了多个模板参数,允许用户在编译时进一步自定义函数的结果.

是否有使用所有这些帮助程序类的替代方法?它变得非常混乱,难以阅读.

理想情况下,这是我想写的:

enum class Sort{Alphabetic, Unsorted};  
template<Sort TS> struct DoSomethingHelper
{
    static void(vector<string>& mTarget)
    {
         // do something with mTarget
         static_if(TS == Sort::Unsorted) { /* do nothing */ }
         static_if(TS == Sort::Alphabetic) { sort(begin(mTarget), end(mTarget)); }
    }   
};
Run Code Online (Sandbox Code Playgroud)

sya*_*yam 17

由于您的值在编译时已知(非模板类型参数),因此您可以完美地编写"正常" if:

template<Sort TS>
void someFunction(vector<string>& mTarget)
{
     if (TS == Sort::Alphabetic) { sort(begin(mTarget), end(mTarget)); }
     // else if (TS == Sort::Unsorted) {}
}
Run Code Online (Sandbox Code Playgroud)

编译器将执行常量折叠死代码消除(当然,如果启用了这些优化),结果将与使用假设的结果完全相同static_if.

  • 它完全不受标准保证,但它是允许的(通过as-if子句:如果你不能达到死代码,它是相同的 - 如果它不存在),但在任何非平凡的优化级别,我从来没有见过单个C++编译器*没有*做到这一点.为了便于携带,请将其与编译时显而易见的值进行简单比较.请注意,如果条件为真,则分支中的代码必须合法才能编译. (2认同)
  • 我决定"信任编译器",并使用简单的if/else if指令重构我现有的代码.https://github.com/SuperV1234/SSVUtils/commit/906b4329120e6191e6ec10ee057f7f879320657b (2认同)

Mat*_* M. 11

我担心对使用的误解static_if.

当然你可以使用static_if(或者你想要的任何技巧)尝试进行一些优化,但这不是它的第一个目标.

第一个目标static_if语义.让我来证明这一点std::advance.典型的实现std::advance将使用类型开关在编译时选择O(1)实现(用于随机访问迭代器)和O(n)实现(用于其他实现):

template <typename It, typename D>
void advance_impl(It& it, D d, random_access_iterator_tag)
{
    it += d;
}

template <typename It, typename D>
void advance_impl(It& it, D d, bidirectional_iterator_tag)
{
    if (d > D(0)) { for (D i(0); i < d; ++i) { ++it; } }
    else          { for (D i(0); i > d; --i) { --it; } }
}

template <typename It, typename D>
void advance_impl(It& it, D d, input_iterator_tag)
{
    for (D i(0); i < d; ++i) { ++it; }
}
Run Code Online (Sandbox Code Playgroud)

最后:

template <typename It, typename D>
void advance(It& it, D d)
{
    typename std::iterator_traits<It>::iterator_category c;
    advance_impl(it, d, c);
}
Run Code Online (Sandbox Code Playgroud)

为什么不在if这种情况下只使用一个?因为它不会编译.

  • 双向迭代器不支持 +=
  • 输入迭代器(或前向迭代器)不支持 --

因此,实现该功能的唯一方法是仅使用给定类型的可用操作静态地调度到函数.