次の質問は、はるかに大きなコードから集約されています。したがって、いくつかの式は過度のまたは不必要であるように見えますが、元のコードには重要です。コンパイル時のテンプレートとconstexprの控除コンパイラと最適化フラグによって異なります
は時定数と、単純なコンテナクラスをコンパイル含まれている構造体を有する考えてみましょう:
template<typename T> struct CONST
{
static constexpr T ONE()
{
return static_cast<T>(1);
}
};
template<typename T> class Container
{
public:
using value_type = T;
T value;
};
は今value_type
を提供するタイプのための「専門」を持つテンプレート機能を有する:
template<typename T> void doSomething(const typename T::value_type& rhs)
{}
今、私は、これが動作する必要があることを、期待:
template<typename T> class Tester
{
public:
static constexpr T ONE = CONST<T>::ONE();
void test()
{
doSomething<Container<T>>(ONE);
}
};
興味深い点は、コンパイラはTester<T>::ONE
の定義に不満はないが、その使用法です。さらに、CONST<T>::ONE()
、またはONE
の代わりにstatic_cast<T>(ONE)
を関数呼び出しで使用すると、それは不平を言っていません。しかし、どちらもコンパイル時に認識され、したがって使用可能でなければなりません。 私の最初の質問は次のとおりです。コンパイラは、コンパイル時に計算を行うケースでも、どこで動作しますか?
-std=c++14
フラグを使用して、g++-5
,g++-6
、clang-3.8
コンパイラで確認しました。彼らはすべて、私が知っている限り、標準で使用されているため、サポートされている必要がありますが、
undefined reference to `Tester<int>::ONE'
でも文句を言います。興味深いことに、最適化フラグO1
、O2
またはO3
を追加するとすぐに、コンパイルは成功します。だから私の2番目の質問です:最適化フラグがアクティブな場合、コンパイル時の計算を行うだけのコンパイラの戦略はありますか?私は、少なくともコンパイル時定数として宣言されているものは、常にと推測されました!
私の質問の最後の部分は、NVIDIA nvcc
コンパイラ(バージョン8.0)です。 -std=c++11
にしか渡すことができないため、一部の機能は一般的にはカバーされていない場合があります。しかし、上記のホストコンパイラの1つを使用すると、最適化フラグが渡されても、
が報告されます。これは明らかに上記と全く同じ問題ですが、上記の質問はもっと学問的ですが(問題を解決するために単純に最適化フラグを使用できるため)、ここでは本当に問題です(私には分かりません上記の回避策を使用するとコンパイル時に何が行われますか?またこれも醜いです)。だから私の3番目の質問です:デバイスコードでも最適化を使用する方法はありますか?事前に
#include <iostream>
#include <cstdlib>
#ifdef __CUDACC__
#define HD __host__ __device__
#else
#define HD
#endif
template<typename T> struct CONST
{
HD static constexpr T ONE()
{
return static_cast<T>(1);
}
};
template<typename T> class Container
{
public:
using value_type = T;
T value;
};
template<typename T> HD void doSomething(const typename T::value_type& rhs) {}
template<typename T> class Tester
{
public:
static constexpr T ONE = CONST<T>::ONE();
HD void test()
{
doSomething<Container<T>>(ONE);
// doSomething<Container<T>>(static_cast<T>(ONE));
// doSomething<Container<T>>(CONST<T>::ONE());
}
};
int main()
{
using t = int;
Tester<t> tester;
tester.test();
return EXIT_SUCCESS;
}
ありがとう:
次のコードは、NVCCコンパイラのため、純粋なホストのMWEとです!
あなたの質問の最初の部分について見http://stackoverflow.com/questions/8452952/c-linker-error-with-class-static-constexpr –