小编Vit*_*meo的帖子

是static_cast <T>(...)编译时还是运行时?

static_cast<T>(...)在编译时还是在运行时完成的事情?我用Google搜索了但我得到了不同的答案.

此外,dynamic_cast<T>(...)显然是运行时 - 但是呢reinterpret_cast<T>(...)

c++ casting runtime compile-time c++11

12
推荐指数
2
解决办法
7105
查看次数

转发模板成员函数的参数

一个例子


我需要将一些预定义的参数和一些用户传递的参数转发给成员函数.

#define FWD(xs) ::std::forward<decltype(xs)>(xs)

template<class T, class... Ts, class... TArgs>
void forwarder(void(T::*fptr)(Ts...), TArgs&&... xs)
{
    T instance;
    (instance.*fptr)(FWD(xs)..., 0);
    //                           ^
    // example predefined argument
}

forwarder(&example::f0, 10, 'a');   
forwarder(&example::f1, 10, "hello", 5);
Run Code Online (Sandbox Code Playgroud)

这适用于非模板成员函数.

forwarder但是,传递给can 的成员函数指针也指向模板函数.不幸的是,T在这种情况下,编译器无法推断出类型:

struct example
{
    void f0(int, int) { }

    template<class T>
    void f1(T&&, int) { }
};

// Compiles
forwarder(&example::f0, 10);

// Does not compile
forwarder(&example::f1, 10);
Run Code Online (Sandbox Code Playgroud)

错误:

prog.cpp:30:28: error: no matching function for call to 'forwarder(<unresolved overloaded function type>, int)' …
Run Code Online (Sandbox Code Playgroud)

c++ templates variadic-templates type-deduction c++14

12
推荐指数
1
解决办法
502
查看次数

访问lambda尾随返​​回类型中的generalize-captured对象

int main()
{
    auto l = [x = 10]() -> decltype(x) {};
}   
Run Code Online (Sandbox Code Playgroud)

c++ lambda language-lawyer trailing-return-type c++14

12
推荐指数
1
解决办法
234
查看次数

在fold表达式中使用lambdas时出现"未初始化的捕获引用"错误 - clang vs gcc

请考虑以下代码:

template <typename F, typename X0, typename X1, typename... Xs>
auto fold_left(F&& f, X0&& x0, X1&& x1, Xs&&... xs)
{
    auto acc = f(x0, x1);
    return ([&](auto y){ return acc = f(acc, y); }(xs), ...);
}

const std::string a{"a"}, b{"b"}, c{"c"}, d{"d"}, e{"e"};
const auto cat = [](auto x, auto y) { return "(" + x + ", " + y + ")"; };
Run Code Online (Sandbox Code Playgroud)

在调用和打印时fold_left(cat, a, b, c),g ++ 7和clang ++ 5输出:

((a,b),c)


当调用和打印fold_left(cat, a, b, c, …

c++ language-lawyer fold-expression c++17

12
推荐指数
1
解决办法
274
查看次数

是否未定义行为来读取和比较POD类型的填充字节?

今天我遇到了一些大致类似于以下代码段的代码.二者valgrindUndefinedBehaviorSanitizer检测读取未初始化的数据.

template <typename T>
void foo(const T& x)
{
    static_assert(std::is_pod_v<T> && sizeof(T) > 1);
    auto p = reinterpret_cast<const char*>(&x);

    std::size_t i = 1; 
    for(; i < sizeof(T); ++i)
    {
        if(p[i] != p[0]) { break; }
    }

    // ...
}
Run Code Online (Sandbox Code Playgroud)

p[i] != p[0]当传递包含填充字节的对象时,上述工具抱怨比较foo.例:

struct obj { char c; int* i; };
foo(obj{'b', nullptr});
Run Code Online (Sandbox Code Playgroud)

从POD类型中读取填充字节并将它们与其他内容进行比较是不确定的行为?我无法在Standard和StackOverflow中找到明确的答案.

c++ padding undefined-behavior language-lawyer standard-layout

12
推荐指数
1
解决办法
491
查看次数

lambda 主体内广义 lambda 捕获的 `decltype` - gcc vs clang

考虑以下代码:

#include <type_traits>

int main()
{
    auto l = [k = 0]
    {
        static_assert(std::is_same_v<decltype(k), int>);
    };
}
Run Code Online (Sandbox Code Playgroud)
  • clang++ (10.x 和主干)愉快地编译了上面的代码。

  • g++ (10.x 和主干)无法编译上面的代码并出现以下错误:

    error: static assertion failed
       10 |         static_assert(std::is_same_v<decltype(k), int>);
          |                       ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    Run Code Online (Sandbox Code Playgroud)

    显然,g++相信decltype(k)评估为const int

Godbolt.org 上的现场示例

由于数据成员的类型k应该从0(这是一个普通的,非const, int)推导出来,我认为这是一个g++错误。在我的心智模式,这是唯一的事情constoperator()拉姆达的,而不是合成的数据成员k

  • 我的评估是否正确?

  • 标准怎么说?

c++ lambda shadowing language-lawyer c++14

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

从模板参数获取函数arity

如何获得用作模板参数的任意函数类型的arity?

该函数可以是普通函数,lambda或函子.例:

template<typename TFunc>
std::size_t getArity() 
{
    // ...? 
}

template<typename TFunc>
void printArity(TFunc mFunc)
{
    std::cout << "arity: " << getArity<TFunc>() << std::endl;
}

void testFunc(int) { }

int main()
{
    printArity([](){}); // prints 0
    printArity([&](int x, float y){}); // prints 2
    printArity(testFunc); // prints 1
}
Run Code Online (Sandbox Code Playgroud)

我可以访问所有C++ 14功能.

我是否必须为每种函数类型(以及所有相应的限定符)创建特化?或者有更简单的方法吗?

c++ function arity c++11 c++14

11
推荐指数
1
解决办法
1770
查看次数

在基于lambda的foreach循环中模拟`continue;`,`break;`

我是"基于lambda的foreach循环"的粉丝:

class SomeDataStructure
{
    private:
        std::vector<SomeData> data;

    public:
        template<typename TF> void forData(TF mFn)
        {
            for(int i{0}; i < data.size(); ++i)
                mFn(i, data[i]);
        }
};

SomeDataStructure sds;

int main()
{
   sds.forData([](auto idx, auto& data)
   {
       // ...
   });
}
Run Code Online (Sandbox Code Playgroud)

我认为这对于更复杂的数据结构来说是一个很好的抽象,因为它允许用户使用其他参数直观地循环其内容.并且编译器优化应该保证性能等于传统for(...)循环.

不幸的是,像这样使用Lambda表达式显然阻止了使用有时是有用的continue;break;陈述.

sds.forData([](auto idx, auto& data)
{
    // Not valid!
    if(data.isInvalid()) continue;
});
Run Code Online (Sandbox Code Playgroud)

有没有办法模拟continue;break;语句没有任何性能损失,并没有使语法不方便?

c++ lambda loops c++14

11
推荐指数
2
解决办法
3167
查看次数

访问`std :: variant`的不安全,"noexcept"和无开销方式

std::variant 提供以下访问功能:

  • std::get_if:取指针variant,返回指针替代.

    template <std::size_t I, typename... Ts> 
    auto* std::get_if(std::variant<Ts...>* pv) noexcept;
    
    Run Code Online (Sandbox Code Playgroud)
    • 如果pv不是空指针pv->index() == I,则返回指向存储在指向的变量中的值的指针pv.否则,返回空指针值.

      这意味着get_if实现大致如下:

      template <std::size_t I, typename... Ts> 
      auto* std::get_if(std::variant<Ts...>* pv) noexcept
      {
          if(pv == nullptr) return nullptr;
          if(pv->index() != I) return nullptr;
          return &(pv->real_get<I>());
      }
      
      Run Code Online (Sandbox Code Playgroud)
  • std::get:取基准variant,回到参考替代,throw对非法访问.

    template <std::size_t I, typename... Ts>
    auto& std::get(std::variant<Ts...>& v);
    
    Run Code Online (Sandbox Code Playgroud)
    • 如果v.index() == I,则返回对存储的值的引用v.否则,抛出std::bad_variant_access …

c++ variant c++17

11
推荐指数
1
解决办法
354
查看次数

使用模板调用操作符和泛型lambdas重载结构 - gcc vs clang

我发现了一个代码片段,它在clang ++ 4(和trunk)中编译并正常工作,但无法在g ++ 7(和trunk)中编译.我们假设我有以下struct类型:

struct a { void foo() { } };
struct b { void bar() { } };
struct c { void bar() { } };
Run Code Online (Sandbox Code Playgroud)

我想创建一个过载设定的lambda表达式哪些处理a明确,而bc被"捕获"用一个通用的λ auto参数:

auto ol = overload([](a x)   { x.foo(); },
                   [](auto x){ x.bar(); })
Run Code Online (Sandbox Code Playgroud)

当我调用时ol(a{}):

  • 铛++编译和行为与预期:a"匹配"的第一拉姆达,而bc匹配第二个.

  • g ++无法编译,出现以下错误:

    error: 'struct a' has no member named 'bar' …
    Run Code Online (Sandbox Code Playgroud)

c++ lambda overloading language-lawyer c++17

11
推荐指数
1
解决办法
579
查看次数