DMD 拒绝实例化模板:不是模板声明

DMD refuses to instantiate template: not a template declaration

我在 D 中有一个模板化的 class,它将另一个模板作为参数,它是这样开始的:

class RuleVars(alias RuleType, RuleRange, SubstitutionRange)
if (__traits(isTemplate, RuleType)) {

     import std.range.primitives;
     import std.traits;

     import Capsicum.PatternMatching.Engine;

     private {
        static if (isAssociativeArray!RuleRange) {
            alias RuleType = ElementType!(typeof(ruleRange.values));
         } else {
            alias RuleType = ElementType!RuleRange;
         }

        static if (isAssociativeArray!SubstitutionRange) {
            alias SubstitutionType = ElementType!(typeof(ruleRange.values));
        } else {
            alias RuleType = ElementType!RuleRange;
        }

        alias MatchingPolicy = RuleType!(Element, RuleElement);
...

需要注意的重要一点是,如果 RuleType 不是模板,class 将无法实例化。 作为必要,我有一个创建这个 class:

实例的函数
RuleVars!(RuleType, RuleRange, SubstitutionRange) CreateRuleVars(alias  RuleType, RuleRange, SubstitutionRange)(RuleRange leftHandSide, SubstitutionRange rightHandSide) {
    return new RuleVars!(RuleType, RuleRange, SubstitutionRange)(leftHandSide, rightHandSide);
}

但是,当我尝试像这样实例化 class 时:

CreateRuleVars!UnboundRules([0 : 'a', 2 : 'b', 4 : 'a', 6 : 'b'],
            [1 :'a', 3 : 'a', 4 : 'b', 6 : 'b'])

我收到以下错误:

source\Capsicum\PatternMatching\RuleSet.d(25,26): Error: template instance RuleType!(Element, RuleElement) RuleType is not a template declaration, it is a alias
source\Capsicum\PatternMatching\RuleSet.d(73,1): Error: template instance Capsicum.PatternMatching.RuleSet.RuleVars!(UnboundRules, char[int], char[int]) error instantiating
source\Capsicum\PatternMatching\RuleSet.d(127,31):        instantiated from here: CreateRuleVars!(UnboundRules, char[int], char[int])

它抱怨这个特定的行:

    alias MatchingPolicy = RuleType!(Element, RuleElement);

这里传的具体模板自己使用实例化证明是可以用的,应该问题不大。也明显是模板,不然模板参数匹配就失败了。官方D文中表示模板可以像这样作为模板参数传递:

class Foo(T, alias C)
{
    C!(T) x;
}

据我所知,我做的是正确的。有什么想法吗?

问题是这些行:

alias RuleType = ElementType!(typeof(ruleRange.values));

您重新定义了一个隐藏参数的局部符号 RuleType,因此后续行引用该局部别名而不是您要使用的参数。

有趣的是,这可能是编译器中的诊断错误。如果你用常规参数做了类似的事情:

    void main(string[] args) {
            int args;
    }

编译器会标记它:

Error: variable args is shadowing variable aa.sub.main.args

因为这几乎肯定是一个错误;您肯定打算使用两个单独的名称,这样您仍然可以引用参数(否则您只能引用局部变量!)。但是好像编译器没有对模板参数进行这样的测试。