編輯
你真正要求的是使寫作該代碼是一個錯誤,我很難過說這不是真的可能。我不認爲那裏有一個IDE可以防止你編寫無效的代碼。但是,如果您在下面實現了一個解決方案(編譯時),那麼一個足夠先進的IDE將能夠向您提供有關在編譯之前編寫的代碼很糟糕的信息。
像Visual Studio編譯器基本上將「編譯」你的東西在後臺,然後強調糟糕的代碼(讀:不會編譯)用紅色波浪線。
下面
您認爲一對夫婦爲您Class2
結構的可能性,所以,讓我們將每個
編譯時檢查答案:
首先,我們將與您Class1
開始基本上你定義它:
template<int i>
struct Class1{
// how to define a "foo" function that is only callable
// if Class2's j is evenly divisble by i?
};
你的第一個可能性是Class2
有一個模板化j
參數:
template<int j>
struct Class2
{
//...
};
很好的解決,這將是對模板Class1
的foo
方法,然後包括static_assert
,這是一個編譯時斷言。這是可行的,因爲編譯時已知i
和j
。
現在Class1
看起來是這樣的:
template<int i>
struct Class1{
template<int j>
void foo()
{
static_assert(j%i==0, "j is not evenly divisible by i");
std::cout << "j is evenly divisble by i" << std::endl;
}
};
而且Class2
可以撥打foo
這樣的:
template<int j>
struct Class2
{
void CallFoo()
{
Class1<2> c1;
c1.foo<j>(); // works
//Class1<3> c2;
//c2.foo<2>(); // fails static assert
}
};
Demo
你提到的另一種可能性是,Class2
可以有一個成員變量爲j
。你可以做到這一點,只要該成員變量是constexpr
(也static
結果):
struct Class2
{
static constexpr int j = 4;
void CallFoo()
{
Class1<2> c1;
c1.foo<j>(); // works
//Class1<3> c2;
//c2.foo<2>(); // fails static assert
}
};
constexpr
定義編譯時常在這裏。所以保證在編譯時知道這個值,我們的static_assert
就可以工作。
如果j
是不是constexpr
那麼我們不能實現我們的編譯時斷言。在這一點上你退居運行時異常處理:
template<int i>
struct Class1{
void foo(int j)
{
if (j%i != 0)
throw std::invalid_argument("j is not evenly divisible by i");
std::cout << "j is evenly divisble by i" << std::endl;
}
};
struct Class2
{
int j = 4;
void CallFoo()
{
Class1<2> c1;
c1.foo(j); // works
j = 3;
c1.foo(j); // throws
}
};
Demo
你嘗試過'static_assert'嗎? – krzaq
@krzaq看到我對建議答案的評論。 – ShS