【发布时间】:2019-06-29 23:47:48
【问题描述】:
我的代码需要测试各种像素类型的“有效性”。例如,如果浮点像素为std::isnan() 报告true,则它们是无效的。
所以我有一个“验证器”模板结构,我专门针对我的各种像素类型(这里只针对float)。我的代码使用全局模板函数通过 SFINAE 调用正确的重载
// Dummy implementation breaks compilation if no overload found.
template<class PEL, typename Enable=void> struct pixel_validator { };
template<class PEL>
struct pixel_validator<PEL, typename std::enable_if<std::is_floating_point<PEL>::value>::type>
{
static bool validate(const PEL& p) { return !std::isnan(p); }
};
template<class PEL>
inline bool is_valid_pixel(const PEL& p)
{
// Dispatch to validator above
return pixel_validator<PEL>::validate(p);
};
void main
{
float x = 1.0f;
std::cout << "is it valid ?" << std::boolalpha << is_valid_pixel(x);
}
这个例子工作得很好。选择了float 的pixel_validator 特化。一切都很好。
但后来我尝试通过专门针对float 的自定义版本“std::enable_if”来减少模板表达式的冗长以清晰起见。
template<class T, class VAL=T>
struct enable_if_floating
: std::enable_if<std::is_floating_point<T>::value, VAL>
{};
所以现在不要写这个:
std::enable_if<std::is_floating_point<PEL>::value>::type
我会写
enable_if_floating<PEL>::value
...所以我的验证器变成:
template<class PEL>
struct pixel_validator<PEL, typename enable_if_floating<PEL>::type>
{
static bool validate(const PEL& p) { return !std::isnan(p); }
};
不幸的是,在我更改“pixel_validator”以使用它的那一刻,代码无法构建。我的enable_if_floating 不起作用,因此 Visual Studio 找不到合适的专业化。我的输出也就不足为奇了。
1>------ Build started: Project: TestApp7, Configuration: Debug Win32 ------
1>TestApp7.cpp
1>C:\Test\TestApp7\TestApp7.cpp(62,34): error C2039: 'validate': is not a member of 'pixel_validator<PEL,void>'
1>C:\Test\TestApp7\TestApp7.cpp(62,34): error C2039: with
1>C:\Test\TestApp7\TestApp7.cpp(62,34): error C2039: [
1>C:\Test\TestApp7\TestApp7.cpp(62,34): error C2039: PEL=float
1>C:\Test\TestApp7\TestApp7.cpp(62,34): error C2039: ]
1>C:\Test\TestApp7\TestApp7.cpp(62): message : see declaration of 'pixel_validator<PEL,void>'
1>C:\Test\TestApp7\TestApp7.cpp(62): message : with
1>C:\Test\TestApp7\TestApp7.cpp(62): message : [
1>C:\Test\TestApp7\TestApp7.cpp(62): message : PEL=float
1>C:\Test\TestApp7\TestApp7.cpp(62): message : ]
1>C:\Test\TestApp7\TestApp7.cpp(82): message : see reference to function template instantiation 'bool is_valid_pixel<float>(const PEL &)' being compiled
1>C:\Test\TestApp7\TestApp7.cpp(82): message : with
1>C:\Test\TestApp7\TestApp7.cpp(82): message : [
1>C:\Test\TestApp7\TestApp7.cpp(82): message : PEL=float
1>C:\Test\TestApp7\TestApp7.cpp(82): message : ]
1>C:\Test\TestApp7\TestApp7.cpp(62,1): error C3861: 'validate': identifier not found
1>Done building project "TestApp7.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
我的问题是,为什么?我的enable_if_floating 有什么问题?
注意:我什至把这段代码放在我的main() 中,只是为了进行完整性检查。如果我的模板不好,我预计 static_assert() 会失败,但事实并非如此。
// Sanity check #2. Does my enable_if_floating test reports that float
// enables because it's numeric? If not then the static_assert below should fail
using float_type = enable_if_floating<float>::type;
static_assert(std::is_same_v<float_type, float>, "Not same as float...");
另请注意:我的真实世界代码使用的谓词比这个简单示例节省了更多空间
【问题讨论】:
-
enable_if_floating的定义中std::enable_if的第二个参数是不必要的,看来
-
这个想法是使用它,就像在 enable_if 中使用第二个参数一样;也就是说,有时我希望它评估的类型(当它被选择时)不同于提供的类型 T
-
明确地说,我发布这个问题不是为了寻找解决方法,我发布它是为了了解为什么这种方法不起作用
标签: c++11 templates template-meta-programming sfinae visual-studio-2019