2017-05-05 95 views
4

我试图创建程序,只有当模板被实例化时(它将用于低级驱动程序初始化)才会执行一些代码。 现在我有以下解决方案。强制模板静态成员实例

class Initializer 
{ 
public: 
    Initializer(){ 
     // This code is executed once 
    } 

    void silly() const{ 

    } 
}; 

template <class T> 
class Proxy{ 
protected: 
    static const Initializer init; 
}; 

template<class T> 
const Initializer Proxy<T>::init; 

template<class T> 
class MyTemplate : public Proxy<void>{ 
public: 
    static void myMethod1(){ 
     init.silly(); 

     // ... Something useful 
    } 

    static void myMethod2(){ 
     init.silly(); 

     // ... Something useful 
    } 
}; 

Initializer默认的构造函数只有在情况下,我打电话myMethod1()myMethod2()某处被执行。

但是有没有办法摆脱那些init.silly();行?

+0

“强制实例化:”和“检查实例化”是两个完全不同的事情。 –

+0

你是否想为'Proxy'的每个实例创建'Initializer'?例如。如果你创建'Proxy '和'Proxy ',那么'Initializer'会被构造两次? – Pavel

+0

不,我只想创建一个'Initializer'实例。我将永远继承'代理'。 – valentin

回答

2

你的问题是,模板的成员没有被实例化,除非被引用。

不需要调用init.silly(),你可以参考成员:

static void myMethod1(){ 
     (void)init; 

     // ... Something useful 
    } 

或者,如果你想init是绝对总是定义,你可以显式实例吧:

template<> 
const Initializer Proxy<void>::init{}; 
+0

它更好,但仍需要额外的一行代码。 如果我使用'init'的显式实例化,即使未实例化MyTemplate,它的构造函数也会执行。情况并非如此。 – valentin

1

模板低级别的驱动程序初始化?..我会尽量使它尽可能C :)以确保确切的行为。

你可以做这样的事情或许是:

class Initializer 
{ 
public: 
    Initializer() { 
     // This code is executed once 
    } 
}; 

template <class T> 
class Proxy { 
protected: 
    Proxy() 
    { 
     static Initializer init; 
    } 
}; 

template<class T> 
class MyTemplate : public Proxy<void> { 
public: 
    void myMethod1() { 
     // ... Something useful 
    } 

    void myMethod2() { 
     // ... Something useful 
    } 
}; 

所有的代码只使用静态函数并没有真正说明为什么你会用类和模板。通过我的更改,我创建了myMethod1myMethod2非静态,Proxy()构造函数创建了Initializer一次。

请注意,由于所有模板混乱,您可能会在实例化代理模板时多次执行您的Initializer。你真的认真吗?如果不是,则转换为清晰可读的代码,该代码不会出现此意外结果。这也将是更好的维护和可读性为他人:

class Initializer 
{ 
    Initializer() { 
     // This code is executed once 
    } 
public: 
    void init() 
    { 
     static Initializer init; 
    } 
}; 


template<class T> 
class MyTemplate { 
public: 
    static void myMethod1() { 
     Initializer::init(); 
     // ... Something useful 
    } 

    static void myMethod2() { 
     Initializer::init(); 
     // ... Something useful 
    } 
}; 

这使得绝对清楚地表明Initializer将创建一次myMethod1myMethod2调用前。如果没有任何东西叫你Initializer::init那么Initializer的代码应该在链接时被删除。

+0

哦,是的!这更干净。它还不必担心有关模板成员何时被实例化的详细问题 - 这只是a)开发人员感到困惑的标准的黑暗角落; b)*编译器*开发者偶尔会感到困惑。 –