我有一个模板类/结构,如下所示:
template <typename T, typename U>
struct S
{
unsigned int operator()(T t, U u) const;
};
Run Code Online (Sandbox Code Playgroud)
我想确保专业化尊重这个界面.
不幸的是,我可以使用不同的返回类型来专门化这个结构.例如,如果我部分专门返回bool而不是unsigned int,我希望得到编译器错误,但编译器似乎并不关心:
template <typename T>
struct S<T,nullptr_t>
{
bool operator()(T t, nullptr_t u) const { return 2; }
};
Run Code Online (Sandbox Code Playgroud)
示例 @ Ideone.com
在上面的示例中,应该返回专用版本,2但是由于返回类型是bool,返回值将被转换true为然后显示为1.
为什么编译器会接受这个?
如何防止程序员使用错误的返回类型(甚至错误的参数)专门化模板?
我知道我可以在基本模板类/结构中使用虚方法实现我想要的,并override在子代中使用关键字:
使用覆盖的解决方案(不编译,这很好)
但是拥有一个虚拟方法肯定会创建一个虚拟表,我想尽可能地避免这种情况,特别是因为我在运行时不需要虚拟表.除非有一个技巧可以在不构建虚拟表的情况下做同样的事情?
另外,我知道问题会更简单,如果我可以部分专门化方法或者我可以依赖非部分专业化,但前者在C++ AFAIK中是不可能的,后者不包括我在程序中需要的情况.
假设我有一个程序输出:
abcd
l33t
1234
Run Code Online (Sandbox Code Playgroud)
我会用它来模拟printf 'abcd\nl33t\n1234\n'.我想同时将这个输出提供给两个程序.我的想法是使用进程替换tee.假设我想将输出的副本提供给grep:
printf 'abcd\nl33t\n1234\n' | tee >(grep '[a-z]' >&2) | grep '[0-9]'
Run Code Online (Sandbox Code Playgroud)
我使用Bash 4.1.2(Linux,CentOS 6.5)得到以下内容,这很好:
l33t
1234
abcd
l33t
Run Code Online (Sandbox Code Playgroud)
但是如果进程替换没有被重定向到stderr(即没有>&2),就像这样:
printf 'abcd\nl33t\n1234\n' | tee >(grep '[a-z]') | grep '[0-9]'
Run Code Online (Sandbox Code Playgroud)
然后我得到:
l33t
1234
l33t
Run Code Online (Sandbox Code Playgroud)
这就像进程替换的stdout(第一个grep)被管道(第二个grep)之后的进程使用.除了第二个grep已经自己读取东西,所以我想它不应该考虑第一个grep中的东西.除非我弄错了(我肯定是).
我错过了什么?