C++ 默认模板函数参数

C++ 默认模板函数参数,c++,c++17,language-lawyer,C++,C++17,Language Lawyer,参考以下代码: #include <iostream> #include <variant> #include <limits> using namespace std; template < bool bitwise = false, typename T> // template <typename T, bool bitwise = false> // ^ wont work! error: no matching fu

参考以下代码:

#include <iostream>
#include <variant>
#include <limits>

using namespace std;

template < bool bitwise = false, typename T>
// template <typename T,  bool bitwise = false>  
// ^ wont work! error: no matching function for call to 'func<true>(int, int)'

bool func(T a, T b) {
    if constexpr(bitwise) {
        return a & b;
    }
    else {
        return a && b;
    }
}
int main()
{
    cout << func(7,1) << endl;
    cout << func<true>(7,1) << endl;
}
为什么我必须在模板列表中首先按位指定参数?编译器可以从函数arg推断出T,那么为什么在这种情况下按位需要是第一个呢


Wandbox:

这是因为这个电话:

cout << func<true>(7,1) << endl;
这将使用true作为模板的第一个也是唯一的模板参数来实例化模板


实例化模板时,任何显式模板参数都会分配给模板声明中的初始参数,并且任何剩余参数都必须是可推断的。这使得模板声明中给定的模板参数顺序成为唯一有效的顺序。

谢谢!但是为什么呢?这只是一条规则吗?我知道发生了什么,但为什么会发生这种情况?对不起,如果这是太多的要求,因为一个评论,这就是如何C++工作几乎是简短的答案。当只指定一些模板参数时,必须有一组明确的规则来确定哪些模板参数被显式指定,哪些模板参数必须被推导。编译器不会尝试所有可能的组合,直到找到一个有效的组合。因此,规则是:实例化模板时给出的显式模板参数与模板声明中的初始参数一致,我想一个更好的问题应该是,为什么该语言允许用户覆盖必须推导的模板类型?如果用户真的需要,静态转换应该足够了。我想我可以用auto来强制演绎,但这在C++11之前是行不通的。也许我应该考虑在哪些情况下,忽略推导类型中的类型会破坏现有的代码/模式