假设你想在调用函数时避免缩小
void foo(char c) { /* ... */ }
foo(4); // get a compilation error here
答案 0 :(得分:1)
您可以在具有
的T上使用类模板1)不同类型X上的模板构造函数,当参数不是T时尝试实例化类
2)一个带有T作为参数的构造函数,用于处理您使用确切类型实例化类的情况
#include <iostream>
// g++-4.9 -Werror=narrowing -std=c++11 main2.cc
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55783
template <typename T>
struct no_narrowing
{
using type = T;
// this template constructor lets you try to
// instantiate a no_narrowing using a different
// type. if Narrowing would take place
// value{ val } takes care of it
template <typename X>
no_narrowing(X val) : value{val} {}
// if type is exactly T we use this
no_narrowing(type val) : value{val} {}
operator type() const { return value;}
type value;
};
template <typename T>
using nn = no_narrowing<T>;
void print(nn<char> v)
{
std::cout << v << std::endl;
}
int main(int argc, char *argv[])
{
int i = 2;
print('d');
print(i); // this will not compile
return 0;
}
答案 1 :(得分:1)
您可以定义目标函数和转发模板重载,以尝试非缩小转换为目标类型( DEMO ):
void foo(char) {}
template <typename T>
void foo(T&& t) { foo(char{std::forward<T>(t)}); }
foo('a');
// foo(4); // ill-formed
foo({4});
// foo(0); // ill-formed
foo({0});
// foo(u'a'); // ill-formed
foo({u'a'});
int i = 2;
// foo(i); // ill-formed
// foo({i}); // ill-formed
这有一个很好的优势,客户端可以通过传递一个braced-init-list强制转换。由于braced-init-list阻止了模板推导,因此只能通过重载决策来选择目标函数。即使例如foo(4)
与模板重载相匹配且格式错误 - 由于int
通常无法缩小,因此char
无法转换为foo({4})
- 4
格式正确char
可以转换为{{1}}而不会缩小。