相关疑难解决方法(0)

"constexpr if"vs"if"with optimizations - 为什么需要"constexpr"?

C++ 1z将引入"constexpr if" - 如果将根据条件删除其中一个分支.似乎合理有用.

但是,没有constexpr关键字是不可能的?我认为在编译期间,编译器应该知道编译时间是否已知.如果是,即使是最基本的优化级别也应该删除不必要的分支.

例如(参见godbolt:https://godbolt.org/g/IpY5y5 ):

int test() {
    const bool condition = true;
    if (condition) {
      return 0;
    } else {
      // optimized out even without "constexpr if"
      return 1;
    }
}
Run Code Online (Sandbox Code Playgroud)

Godbolt探险家表示,即使是带有-O0的gcc-4.4.7也没有编译"返回1",所以它实现了constexpr所承诺的.显然,当条件是constexpr函数的结果时,这样的旧编译器将无法这样做,但事实仍然存在:现代编译器知道条件是否为constexpr,并且不需要我明确地告诉它.

所以问题是:

为什么"constexpr if"需要"constexpr"?

c++ constexpr c++17 if-constexpr

39
推荐指数
1
解决办法
1455
查看次数

if/else在C++的编译时?

请考虑以下代码:

#include <iostream>
#include <type_traits>

template<typename T> class MyClass
{
    public:
        MyClass() : myVar{0} {;}
        void testIf() {
            if (isconst) {
                myVar;
            } else {
                myVar = 3;
            }
        }
        void testTernary() {
            (isconst) ? (myVar) : (myVar = 3);
        }

    protected:
        static const bool isconst = std::is_const<T>::value;
        T myVar;
};

int main()
{
    MyClass<double> x;
    MyClass<const double> y;
    x.testIf();
    x.testTernary();
    y.testIf(); // <- ERROR
    y.testTernary(); // <- ERROR
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

对于x(非常量),没有问题.但是,即使在编译时知道if/else中的条件,y(const数据类型)也会导致错误.

是否有可能在编译时不编译错误条件?

c++ templates if-statement compilation

14
推荐指数
3
解决办法
2万
查看次数

如果vs constexpr里面的constexpr函数

最近,我修改了一些if constexprif我constexpr功能,发现他们仍然正常工作,并能进行评估时,编译时间.这是一个最小的案例:

template<int N>
constexpr bool is_negative()
{
    if constexpr  (N >= 0) return false;
    else  return true; 
}
int main()
{
    constexpr  bool v = is_negative<1>();
}
Run Code Online (Sandbox Code Playgroud)

live demo

在上面的例子中,N必须在编译时知道因为它是非类型模板参数,所以if constexpr在这里工作正常.然而,这是一个constexpr功能,因此,IIRC,它是可以让即使我更换一个返回值if constexprif:

template<int N>
constexpr bool is_negative()
{
    if  (N >= 0) return false;
    else  return true; 
}
int main()
{
    constexpr  bool v = is_negative<1>();
}
Run Code Online (Sandbox Code Playgroud)

live demo

cppref来看,所有的要求A constexpr function …

c++ compile-time constexpr if-constexpr

3
推荐指数
1
解决办法
306
查看次数

`if constexpr` vs`if`根据编译器优化和代码性能

考虑一个func非常重要的功能模板.它可以用T=Type1其他类型实例化.部分功能逻辑依赖于T它的实例化.

可以明确地使用if constexpr(代码B)或使用香草if代替(代码A),而编译器可能优化代码.

但是,我想知道,没有constexpr(代码A)的实现有何不同?编译器是否能够if在实例化时检测(在代码A中)哪个分支在编译时使用?它仍然(换码)生成代码效率不高?

代码A. 没有 if constexpr:

template<class T>
void func(T argument)
{
    // some general type-independent logic
    if (std::is_same<Type1,T>::value)
    {
        // do something
    }
    else
    {
        // do something else
    }
    // some general type-independent logic
}
Run Code Online (Sandbox Code Playgroud)

代码B. if constexpr:

template<class T>
void func(T argument)
{
    // some general type-independent logic
    if constexpr (std::is_same<Type1,T>::value)
    {
        // …
Run Code Online (Sandbox Code Playgroud)

c++ c++17 if-constexpr

2
推荐指数
1
解决办法
181
查看次数

如何在模板函数中实现模板类类型?

我想为STL容器设计一个打印功能,包括:std::vector, std::map, std::unodered_map, std::set, std::unordered_set, std::list....

理想的函数如下所示:

template<typename T>
void Show(const T& t)
{
    if (istype(t, std::vector)) 
    {  
        // here is a presudo code
        // print vector
        for (auto i: t) cout << i << endl;
    } 
    else if (istype(t, std::unordered_map)) 
    {
        // print unordered_map
    } 
    else 
    {  }
}
Run Code Online (Sandbox Code Playgroud)

我认为问题发生在 istype()

我知道有一些功能std::is_same可以做到这一点。

但是好像只能操作int或者float不能操作std::vector,你能帮帮忙吗?

c++ templates c++-standard-library function-templates c++17

2
推荐指数
1
解决办法
87
查看次数

以 sizeof ... (args) == 0 作为基本情况的参数包的函数无法编译

这是我的函数的代码:

#include <iostream>
#include <type_traits>
#include <algorithm>

template <typename Head, typename ... Args>
std::common_type_t<Head, Args...> mx(Head n, Args ... args)
{
    if (sizeof ... (args) == 0)
        return n;
    else
        return std::max(n, mx(args ...));
}

int main()
{
    std::cout << mx(3, 4, 5);
}
Run Code Online (Sandbox Code Playgroud)

我遇到编译错误:

main.cpp:在 'std::common_type_t<Head, Args ...> mx(Head, Args ...) 的实例化中 [with Head = int; 参数 = {}; std::common_type_t<Head, Args ...> = int]': main.cpp:11:24:
从 'std::common_type_t<Head, Args ...> mx(Head, Args ...) 递归地需要[头= int; 参数 = {int}; std::common_type_t<Head, Args …

c++ variadic-functions variadic-templates

2
推荐指数
1
解决办法
254
查看次数

查找 C++ 二维数组的行列式时出错

我正在使用 C++ 和 g++(版本 13.2.1),并且我正在创建一个Determinant<m>接受std::array<std::array<int,m>,m>参数类型并返回该矩阵的行列式的函数。

\n

以下是我写的代码。

\n

行列式:

\n
template <int m>\nint Determinant(std::array<std::array<int,m>,m> arr){\n\n    if(m == 2){\n      return arr[0][0]*arr[1][1] - arr[0][1]*arr[1][0];\n    }else if(m >2){\n      int ans = 0;\n      for(int i =0;i < m;i++){\n        ans += arr[0][i]*Determinant<m-1>(slc<m,m>( arr,i,0 ))*(i%2 ? 1:-1);\n      }\n      return ans;\n    }else{\n      return -1;\n\n    }\n  }\n
Run Code Online (Sandbox Code Playgroud)\n

slc :返回一个切片(不是真正的切片,只是删除一行和一列)

\n
template <int m, int n>\nstd::array<std::array<int,(n-1)>,(m-1)> slc(std::array<std::array<int,n>,m> arr, int i,int j){\n  std::array<std::array<int,(n-1)>,(m-1)> ans;\n\n  for(int x = 0;x < m;x ++){\n    for (int y = …
Run Code Online (Sandbox Code Playgroud)

c++ recursion templates matrix determinants

2
推荐指数
1
解决办法
78
查看次数

为什么会编译“if constexpr”的错误分支?

为什么这段代码在编译时出错?我对“ ”的了解(以及这个if constexpr表明该else块不应该被编译。

if constexpr (true) {
    int a = 10;
} else {
    int b = 10
}
Run Code Online (Sandbox Code Playgroud)

错误是:

error: expected ‘,’ or ‘;’ before ‘}’ token
Run Code Online (Sandbox Code Playgroud)

使用的编译器:g++ version 7.5.0
编译时我使用了-std=c++17标志。

PS缺少的';' 是故意的,只是为了检查是否else正在编译。

c++ constexpr c++17 if-constexpr

0
推荐指数
1
解决办法
232
查看次数

为什么我需要默认求和函数来实现可变参数模板求和?

我想计算提供给 function 的任意数量的参数的总和sum。假设给予函数的整数将满足operator+.

如果我注释掉该函数sum()(没有参数的函数),则代码无法编译。如果我取消注释,代码会编译并运行,但永远不会命中 function sum()

我似乎无法理解为什么我们需要有sum()功能,因为我正在使用条件sizeof...(Args)

如果有人能帮助我理解这一点,我会非常感激吗?

/*
int sum() 
{
    std::cout << "Sum with 0 Args" << std::endl;
    return 0;
}
*/

template <typename T, typename...Args>
T sum(T first, Args...args) 
{
    // std::cout << sizeof...(Args) << std::endl;
    if (sizeof...(Args) != 0) 
    {
        return first + sum(args...);
    }
    else 
    {
        std::cout << "Found 0 args" << std::endl;
        return first;
    }
}

int main()
{
    std::cout << sum(1, 2, 3) …
Run Code Online (Sandbox Code Playgroud)

c++ templates function-templates variadic-templates c++14

0
推荐指数
1
解决办法
115
查看次数