小编Vit*_*meo的帖子

将类型插入/删除到可变参数模板列表(参数包)

在可变参数模板类型列表(参数包)中实现基于索引的插入和删除类型的最佳方法是什么?

期望的代码/行为:

template<typename...> struct List { /* ... */ };

static_assert(is_same
<
    List<int, char, float>::Insert<int, 0>,
    List<int, int, char, float>
>());

static_assert(is_same
<
    List<int, char, float>::Insert<int, 2>,
    List<int, char, int, float>
>());

static_assert(is_same
<
    List<int, char, float>::Remove<0>,
    List<char, float>
>());

static_assert(is_same
<
    List<int, char, float>::Remove<1>,
    List<int, float>
>());
Run Code Online (Sandbox Code Playgroud)

我尝试了一个基于在最初为空的列表中推回参数的实现,但是它很难读取/维护.参数类似于:

template<typename T, int I, int ITarget, typename TResult> struct InsertImpl;
Run Code Online (Sandbox Code Playgroud)

我不断增加I直到它等于ITarget,推回现有的类型TResult,这是一个List<...>.当I等于ITarget,我推回TTResult为好.

删除类型有一个类似的实现 - 而不是在索引相等时两次推回,我只是跳过了类型.

我的繁琐解决方案将在推送和弹出方面实现插入和删除.我相信推到前面等于 …

c++ templates metaprogramming variadic-templates c++14

5
推荐指数
1
解决办法
1691
查看次数

在 clang 格式的控制语句后中断

BreakBeforeBraces: Allman在我的.clang-format文件中使用,但控制语句中的大括号(例如if, for, while, ...)没有放在自己的行上。

// Currently:
void foo()
{
    while(true) {
        bar();
    }
}

// What I want:
void foo()
{
    while(true) 
    {
        bar();
    }
}
Run Code Online (Sandbox Code Playgroud)

我读过您可以在 中为大括号设置嵌套配置类BraceWrapping,但我无法找出正确的 YAML 语法(以及 sublime text 插件的 JSON 语法),并且找不到任何现有示例。

有没有办法做到这一点?

c++ formatting clang libclang clang-format

5
推荐指数
1
解决办法
2533
查看次数

并行化 CMake 的 `CheckCCompilerFlag`

我在我的默认构建中使用了很多编译器标志- 在我较慢的笔记本电脑上从头开始运行时让 CMake 检查所有这些需要大约 10-15 秒,当我从头开始重建多个项目或切换时,这可能会很烦人之间gccclang用于测试目的。

check_cxx_compiler_flag用来检查编译器标志是否有效,并且每次检查都由 CMake 按顺序运行。

假设 CMake 所做的是尝试编译一个将标志传递给编译器并检查编译是否成功的虚拟文件,我认为理论上可以产生多个编译器进程来并行测试多个编译器标志。不幸的是,我找不到这样做的方法。

有没有办法并行制作 CMake 测试编译器标志(可能通过产生多个编译器进程)

c++ cmake compiler-flags

5
推荐指数
0
解决办法
101
查看次数

通过通用lambda理解Y Combinator

在构建一个基于lambda的小型元编程库时,我有必要在C++ 14泛型lambda中使用递归来实现左折叠.

我自己的解决方案是将lambda本身作为其参数之一传递,如下所示:

template <typename TAcc, typename TF, typename... Ts>
constexpr auto fold_l_impl(TAcc acc, TF f, Ts... xs)
{
    // Folding step.
    auto step([=](auto self)
    {
        return [=](auto y_acc, auto y_x, auto... y_xs)
        {
            // Compute next folding step.
            auto next(f(y_acc, y_x));

            // Recurse if required.
            return static_if(not_empty(y_xs...))
                .then([=]
                    {
                        // Recursive case.
                        return self(self)(next, y_xs...);
                    })
                .else_([=]
                    {
                        // Base case.
                        return next;
                    })();
        };
    });

    // Start the left-fold.
    return step(step)(acc, xs...);
}
Run Code Online (Sandbox Code Playgroud)

step是从递归开始的"主要"lambda.它返回一个具有所需左折签名的函数(累加器,当前项,剩余项......) …

c++ recursion functional-programming y-combinator c++14

5
推荐指数
1
解决办法
782
查看次数

在非`constexpr`上下文中的`constexpr`函数中使用lambda:clang vs gcc

请考虑以下代码(可在gcc.godbolt.org上获得):

template <typename TF>
constexpr auto fn_x(TF f)
{
    return f();
}

constexpr auto get_x()
{
    return fn_x([]{ return 0; });
}

int main()
{
    auto res = get_x();
}
Run Code Online (Sandbox Code Playgroud)

它在g ++ 5.3.x和更新版本(包括g ++ 6.xx)下编译.

它不能在clang ++ 3.7.x和更新版本下编译,并出现以下错误:

error: constexpr function never produces a constant expression [-Winvalid-constexpr]
constexpr auto get_x()
               ^
note: subexpression not valid in a constant expression
        return fn_x([]{ return 0; });                        
Run Code Online (Sandbox Code Playgroud)

使用gcc和clang编译代码的可能解决方案是使用"间接层" decltype,同时摆脱constexpr …

c++ lambda language-lawyer constexpr c++14

5
推荐指数
1
解决办法
231
查看次数

在`boost :: hana :: map`中更新/替换地图值的典型方法

在一个内部更新值(给定键和新值)的规范方法是boost::hana::map什么?

我尝试使用boost::hana::replace_if但它不起作用,map因为它不是Functor- 我可以通过将其转换map为a tuple然后再转换为a 来实现map它,但听起来效率低下.

我目前正在使用的替代方案是调用map::erase_key后跟map::insert.

是否有任何replaceupdate为此目的而设计的功能可能会丢失?或者这是更新价值的"规范"方式?

c++ boost metaprogramming c++14 boost-hana

5
推荐指数
1
解决办法
711
查看次数

检测可调用对象是否为二进制(包括通用约束lambda)

我正在尝试检测可调用对象是否为二进制(即,它是否operator()采用两个参数).我想对lambdas执行此检查,包括泛型lambdas约束泛型lambda (例如,使用尾随std::enable_if_t返回类型).


注意:不是"普通lambda的arity"的副本.我只关心检查泛型lambda是否是二进制的,并且我已经可以为不受约束的泛型lambda不使用其体中的参数的泛型lambda做到这一点.


我目前的方法是应用Kris Jusiak的Boost.DI C++ Now 2015谈话中描述的技术之一:any_type.它基本上是一个可以隐式转换为任何其他类的类.

struct any_type
{
    template <typename T>
    constexpr operator T() const noexcept
    {
        return {};
    }
};
Run Code Online (Sandbox Code Playgroud)

在定义之后any_type,我正在使用检测习惯来检查是否可以使用两个参数调用特定的可调用对象:

template<class T>
using is_binary_callable_impl = decltype(std::declval<T>()(any_type{}, any_type{}));

template <typename T>
using is_binary_callable = std::experimental::is_detected<is_binary_callable_impl, T>;
Run Code Online (Sandbox Code Playgroud)

这种方法适用于非泛型和通用lambda ...

auto unary_nongeneric = [](int){};
auto unary_generic = [](auto){};
auto binary_nongeneric …
Run Code Online (Sandbox Code Playgroud)

c++ lambda c++14 detection-idiom c++17

5
推荐指数
0
解决办法
80
查看次数

在`static_assert`,`if constexpr(...)`和`constexpr`变量之间的模板中对`constexpr` lambdas的评估不一致

(使用g++ 7.0trunk.)

鉴于以下"类型到价值包装"实用程序......

template <typename T>
struct type_wrapper { using type = T; };

// "Wraps" a type into a `constexpr` value.
template <typename T>
constexpr type_wrapper<T> type_c{};
Run Code Online (Sandbox Code Playgroud)

...我创建了以下函数来检查表达式的有效性:

template <typename TF>
constexpr auto is_valid(TF)
{
    return [](auto... ts) constexpr 
    {
        return std::is_callable<TF(typename decltype(ts)::type...)>{};
    };
}   
Run Code Online (Sandbox Code Playgroud)

is_valid功能可以使用如下:

// Evaluates to `true` if `some_A.hello()` is a valid expression.
constexpr auto can_add_int_and_float = 
    is_valid([](auto _0) constexpr -> decltype(_0.hello()){})
        (type_c<A>);

// Evaluates to `true` if `some_int + some_float` is …
Run Code Online (Sandbox Code Playgroud)

c++ lambda constant-expression constexpr c++17

5
推荐指数
1
解决办法
255
查看次数

当static_cast'ing为仅移动类型时,Clang vs. GCC

考虑以下简单的仅移动类:

struct bar {
    constexpr bar() = default;
    bar(bar const&) = delete;
    bar(bar&&)      = default;
    bar& operator=(bar const&) = delete;
    bar& operator=(bar&&)      = default;
};
Run Code Online (Sandbox Code Playgroud)

现在,让我们创建一个包装器:

template <class T>
struct box {
    constexpr box(T&& x)
        : _payload{std::move(x)}
    {}

    constexpr explicit operator T() &&
    {
        return std::move(_payload);
    }

  private:
    T _payload;
};
Run Code Online (Sandbox Code Playgroud)

并测试:

int main()
{
    auto x = box<bar>{bar{}};
    auto y = static_cast<bar&&>(std::move(x));
}
Run Code Online (Sandbox Code Playgroud)

如果使用-std=c++14或以上编译,Clang-6.0对此代码感到满意.但是,GCC-8.1会产生以下错误:

<source>: In function 'int main()':
<source>:29:45: error: invalid static_cast from type 'std::remove_reference<box<bar>&>::type' {aka …
Run Code Online (Sandbox Code Playgroud)

c++ language-lawyer c++14 c++17

5
推荐指数
1
解决办法
199
查看次数

隐式转换运算符与模板构造函数 - 谁应该优先考虑?

请考虑以下代码段:

template <typename>
struct dependent_false { static constexpr auto value = false; };

struct foo
{
    foo() { }

    template <typename T>
    foo(const T&) { static_assert(dependent_false<T>::value, ""); }
};

struct proxy
{
    operator foo() { return foo{};  }
};

int main()
{
    (void) foo{proxy{}};
}
Run Code Online (Sandbox Code Playgroud)

编译时-std=c++17:

  • clang++ (trunk)成功编译代码;

  • g++(trunk)无法编译代码 - 它实例化foo(const T&).

编译时-std=c++11,两个编译器都拒绝代码.C++ 17中新的prvalue实现规则可能会影响此处的行为.

godbolt.org上的实例


这里的正确行为是什么?

  • 标准是否保证foo::foo(const T&)将(或不会)实例化?

  • 标准是否保证隐式转换运算符优先于调用foo::foo(const T&),而不管它是否被实例化?

c++ conversion-operator language-lawyer copy-elision c++17

5
推荐指数
1
解决办法
184
查看次数