【发布时间】:2015-08-31 13:42:19
【问题描述】:
下面的代码可以使用 g++ 4.8.1 (mingw) 以及 http://gcc.godbolt.org/ 上的各种最新 clang 和 gcc 版本正确编译,但是对于 MSVC2013 Update 4,它会失败,显然是由于 typedef typename A<T>::value_type value_type; 行。编译器给出以下错误:
x.cpp(30):错误 C2893:无法专门化函数模板“
void B<C,int>::bar(void)” 使用以下模板参数: 'MemberFn=void C::baz(int)'
更简单的 typedef typedef T value_type; 有效。
我做错了吗?或者这是 Microsoft C++ 编译器中的一个已知错误?
补充问题:
- 从风格的角度来看,假设我可以选择,是在派生类中重新定义类型(例如
typedef T value_type;)还是从基类中引入它们(例如typedef typename A<T>::value_type value_type;,还是在 C++11using typename A<T>::value_type;) 中? (注意:我现在正在对 C++03 兼容性进行套期保值,因此避免使用using。)这里有一些不确定的讨论:Use typedef/using from templated base class in derived class 我问的原因是,如果无论如何首选typedef T value_type;,我不用太担心。
#include <cstdio>
template <typename T>
struct A {
typedef A<T> base_type;
typedef T value_type;
};
template <typename Derived, typename T>
struct B : public A<T> {
typedef Derived derived_type;
//typedef T value_type; // this works
typedef typename A<T>::value_type value_type; // this fails in MSVC 2013
//using typename A<T>::value_type; // this fails in MSVC 2013 too
template<void (derived_type::*MemberFn)(value_type) >
void bar()
{
(static_cast<derived_type*>(this)->*MemberFn)(42);
}
};
struct C : public B<C, int> {
void baz(int i)
{
std::printf("baz(%d)\n", i);
}
void foo()
{
bar<&C::baz>();
}
};
int main(int, char *[])
{
C c;
c.foo();
}
更新 #1: 这是来自框架的简化测试用例。我不是要求对结构进行一般性批评。我不希望结构在没有上下文的情况下有意义。
更新 #2: 这是一个相关问题,讨论 using 与 typename 结合是否有效:C++ template inheritance issue with base types
更新 #3: 我已在 Microsoft Connect 上提交了一份公开的错误报告。如果您可以重现该问题,并认为这是一个错误,请为该错误投票:https://connect.microsoft.com/VisualStudio/feedback/details/1740423
【问题讨论】:
-
MVSC2014 不存在,它要么是 2013 要么是 15,但如果它的更新 4 它可能是 13
-
typedef typename A<T>::value_type value_type;或任何其他版本不应是必需的,因为value_type可以从A继承 -
@Creris 谢谢。我已将标题和问题更新为 MSVC2013。
-
@SimonKraemer
value_type是一个依赖类型。不能无条件使用。你可以(理论上)在任何地方写:typename A<T>::value_type。 -
是的,但是您可以对
typename B<T, T>::value_type执行相同的操作。那你的意思是什么?
标签: c++ templates visual-c++