2012-12-05 150 views
7

如果替换失败涉及模板别名(,例如缺少成员类型名称上的模板别名,如下面的代码段中所示),是否应该触发错误?模板别名和sfinae

锵和gcc似乎对此意见不一:

// some types 
struct bar { }; 

struct foo { 
    typedef void member_type; 
}; 


// template alias 
template<class T> 
using member = typename T::member_type; 


template<class T> 
void baz(...) { } 

// only works for gcc, clang fails with: no type named 'member_type' 
// in 'bar' 
template<class T> 
void baz(member<T>*) { } 


int main(int, char**) { 

    baz<bar>(0);   // picks first 
    baz<foo>(0);   // picks second 

    return 0; 
} 

所以现在的问题是:谁是正确的,为什么?

感谢:-)

+0

'clang -v'说什么?铿锵3.3主干编译代码就好了。 – Xeo

+0

Debian clang版本3.1-8在这里,看起来像我只需要等待。感谢您的反馈意见 ! – max

+0

你可以摆脱模板别名,只是为了简化一点点 – David

回答

4

根据该标准,这显然是海湾合作委员会是正确的,因为别名模板必须立即更换,然后正常/通常SFINAE时T知道后来应用到typename T::member_type

但目前有这个问题,请参阅http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1554

根据会议结果,似乎红clangs行为期望:的T取代将在别名模板(即使在typename T::member_type替代的时间范围内完成,有一个别名无参考模板 - 它仍然需要被引用作为参数类型模式来源的来源,如果这是它的实现方式的话)。


这与另一种情况图案被扔掉的定义时,可能影响实例化语义

template<int I> 
void f(int x[I]); 

int main() { 
    f<0>(nullptr); 
} 

在这种情况下也是如此,在我看来,标准规范地很清楚,该参数是立即被替换为int*,因此实例化工作。见http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1322

+5

“根据会议的结果,看起来clangs的行为是期望的” - 这不会完全消灭任何“EnableIf”别名吗?它似乎非常不希望别名模板不能生成SFINAE软错误。 – Xeo

+0

@Xeo是的,这将是不好的。事实上,clang trunk接受'EnableIf'别名,因此在我看来,提问者观察到的行为只是一个叮叮声虫,而wg21站点上的问题摘要只是令人困惑(恕我直言)。 –

+0

是的,我很困惑,因为我已经评论说主干编译好的代码。 – Xeo